c# - thread - MethodInvoker vs Action para Control.BeginInvoke
thread invoke c# (7)
¿Cuál es más correcto y por qué?
Control.BeginInvoke(new Action(DoSomething), null);
private void DoSomething()
{
MessageBox.Show("What a great post");
}
o
Control.BeginInvoke((MethodInvoker) delegate {
MessageBox.Show("What a great post");
});
Siento que estoy haciendo lo mismo, ¿cuándo es el momento adecuado para usar MethodInvoker
vs Action
o incluso escribir una expresión lambda?
EDITAR: Sé que no hay mucha diferencia entre escribir un lambda vs Action
, pero MethodInvoker
parece estar hecho para un propósito específico. ¿Está haciendo algo diferente?
Ambos son igualmente correctos, pero la documentación para Control.Invoke
establece que:
El delegado puede ser una instancia de EventHandler, en cuyo caso el parámetro del remitente contendrá este control, y el parámetro del evento contendrá EventArgs.Empty. El delegado también puede ser una instancia de MethodInvoker, o cualquier otro delegado que tome una lista de parámetros vacía. Una llamada a un delegado de EventHandler o MethodInvoker será más rápida que una llamada a otro tipo de delegado.
Entonces MethodInvoker
sería una elección más eficiente.
Es una cuestión de preferencia en la mayoría de los casos, a menos que intente reutilizar el método DoSomething (). Además, las funciones anónimas colocarán sus variables de ámbito en el montón, podría hacer que sea una función más costosa.
La acción se define en Sistema, mientras que MethodInvoker se define en System.Windows.Forms: es mejor que utilices Action, ya que es portable a otros lugares. También encontrarás más lugares que aceptan Acción como parámetro que MethodInvoker.
Sin embargo, la documentación indica que las llamadas a los delegados de tipo EventHandler o MethodInvoker en Control.Invoke () serán más rápidas que cualquier otro tipo.
Además de en qué nombre se encuentran, no creo que haya una diferencia funcional significativa entre Action y MethodInvoker, ambos se definen esencialmente como:
public delegate void NoParamMethod();
Como comentario adicional, Action tiene varias sobrecargas que permiten el paso de parámetros, y es genérico para que puedan ser seguros.
No olvide verificar de alguna manera si el control está disponible en este momento, para evitar errores al cerrar el formulario.
if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));
Para cada solución a continuación, ejecuto una iteración 131072 (128 * 1024) (en una secuencia separada). El asistente de rendimiento VS2010 da estos resultados:
- solo lectura MethodInvoker: 5664.53 (+ 0%)
- Nuevo MethodInvoker: 5828.31 (+ 2.89%)
- función emitida en MethodInvoker: 5857.07 (+ 3.40%)
- acción de solo lectura: 6467.33 (+ 14.17%)
- Nueva acción: 6829.07 (+ 20.56%)
Llamar a una nueva Acción en cada iteración
private void SetVisibleByNewAction()
{
if (InvokeRequired)
{
Invoke(new Action(SetVisibleByNewAction));
}
else
{
Visible = true;
}
}
Llamar a un constructor incorporado de solo lectura, Acción en cada iteración
// private readonly Action _actionSetVisibleByAction
// _actionSetVisibleByAction= SetVisibleByAction;
private void SetVisibleByAction()
{
if (InvokeRequired)
{
Invoke(_actionSetVisibleByAction);
}
else
{
Visible = true;
}
}
Llame a un nuevo MethodInvoker en cada iteración.
private void SetVisibleByNewMethodInvoker()
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
}
else
{
Visible = true;
}
}
Llamada a un constructor constructor de solo lectura , MethodInvoker en cada iteración
// private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker
// _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
private void SetVisibleByMethodInvoker()
{
if (InvokeRequired)
{
Invoke(_methodInvokerSetVisibleByMethodInvoker);
}
else
{
Visible = true;
}
}
Llamada a la función emitida en MethodInvoker en cada iteración
private void SetVisibleByDelegate()
{
if (InvokeRequired)
{
Invoke((MethodInvoker) SetVisibleByDelegate);
}
else
{
Visible = true;
}
}
Ejemplo de llamada para la solución de "Nueva Acción":
private void ButtonNewActionOnClick(object sender, EventArgs e)
{
new Thread(TestNewAction).Start();
}
private void TestNewAction()
{
var watch = Stopwatch.StartNew();
for (var i = 0; i < COUNT; i++)
{
SetVisibleByNewAction();
}
watch.Stop();
Append("New Action: " + watch.ElapsedMilliseconds + "ms");
}
Prefiero usar lambdas y Actions / Funcs:
Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
También por MSDN:
MethodInvoker proporciona un delegado simple que se utiliza para invocar un método con una lista de parámetros vacía. Este delegado se puede usar cuando se realizan llamadas al método Invoke de un control, o cuando se necesita un delegado simple pero no se quiere definir uno.
una Acción por otro lado puede tomar hasta 4 parámetros.
Pero no creo que haya ninguna diferencia entre MethodInvoker y Action, ya que ambos simplemente encapsulan a un delegado que no toma un paremter y devuelve el vacío.
Si miras sus definiciones, simplemente verás esto.
public delegate void MethodInvoker();
public delegate void Action();
por cierto, también podría escribir su segunda línea como.
Control.BeginInvoke(new MethodInvoker(DoSomething), null);