Lequel est le plus correct et pourquoi?
Control.BeginInvoke(new Action(DoSomething), null);
private void DoSomething()
{
MessageBox.Show("What a great post");
}
ou
Control.BeginInvoke((MethodInvoker) delegate {
MessageBox.Show("What a great post");
});
J'ai le sentiment que je fais la même chose, alors quel est le bon moment pour utiliser MethodInvoker
contre Action
, ou même pour écrire une expression lambda?
EDIT: Je sais qu'il n'y a pas vraiment de différence entre écrire un lambda et Action
, mais MethodInvoker
semble avoir été créé dans un but précis. Fait-il quelque chose de différent?
Les deux sont également corrects, mais la documentation de Control.Invoke
indique que:
Le délégué peut être une instance de EventHandler, auquel cas l'expéditeur paramètre contiendra ce contrôle, et le paramètre event contiendra EventArgs.Empty. Le délégué peut également être une instance de MethodInvoker, ou tout autre délégué qui prend un vide liste de paramètres. Un appel à un Délégué EventHandler ou MethodInvoker sera plus rapide qu'un appel à un autre type de délégué.
Donc MethodInvoker
serait un choix plus efficace.
Pour chaque solution ci-dessous, j'exécute une série de 131072 (128 * 1024) itérations (dans un thread séparé) .
Appel à un nouveau Action à chaque itération
private void SetVisibleByNewAction()
{
if (InvokeRequired)
{
Invoke(new Action(SetVisibleByNewAction));
}
else
{
Visible = true;
}
}
Appel à un constructeur en lecture seule, intégré, Action à chaque itération
// private readonly Action _actionSetVisibleByAction
// _actionSetVisibleByAction= SetVisibleByAction;
private void SetVisibleByAction()
{
if (InvokeRequired)
{
Invoke(_actionSetVisibleByAction);
}
else
{
Visible = true;
}
}
Appelez un nouveau MethodInvoker à chaque itération.
private void SetVisibleByNewMethodInvoker()
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(SetVisibleByNewMethodInvoker));
}
else
{
Visible = true;
}
}
Appel à un constructeur en lecture seule, construit, MethodInvoker à chaque itération
// private readonly MethodInvoker _methodInvokerSetVisibleByMethodInvoker
// _methodInvokerSetVisibleByMethodInvoker = SetVisibleByMethodInvoker;
private void SetVisibleByMethodInvoker()
{
if (InvokeRequired)
{
Invoke(_methodInvokerSetVisibleByMethodInvoker);
}
else
{
Visible = true;
}
}
Appel de la fonction convertie dans MethodInvoker à chaque itération
private void SetVisibleByDelegate()
{
if (InvokeRequired)
{
Invoke((MethodInvoker) SetVisibleByDelegate);
}
else
{
Visible = true;
}
}
Exemple d'appel pour la solution "Nouvelle action":
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");
}
Je préfère utiliser lambdas et Actions/Funcs:
Control.BeginInvoke(new Action(() => MessageBox.Show("What a great post")));
Action est défini dans System, tandis que MethodInvoker est défini dans System.Windows.Forms. Il est peut-être préférable d’utiliser Action, car il est portable vers d’autres emplacements. Vous trouverez également plus d'endroits qui acceptent Action en tant que paramètre que MethodInvoker.
Toutefois, la documentation indique que les appels aux délégués de type EventHandler ou MethodInvoker dans Control.Invoke () seront plus rapides que tout autre type.
Hormis le nom de la cible où ils se trouvent, je ne crois pas qu'il y ait une différence significative fonctionnelle entre Action et MethodInvoker. Ils sont essentiellement définis comme suit:
public delegate void NoParamMethod();
En passant, Action comporte plusieurs surcharges qui permettent de passer des paramètres - et il est générique afin de pouvoir protéger les types.
Aussi par MSDN:
MethodInvoker fournit un simple délégué utilisé pour invoquer une méthode avec une liste de paramètres void. Ce délégué peut être utilisé lors d'appels à la méthode Invoke d'un contrôle ou lorsque vous avez besoin d'un simple délégué mais que vous ne souhaitez pas en définir vous-même.
par contre, une Action peut prendre jusqu'à 4 paramètres.
Mais je ne pense pas qu'il y ait de différence entre MethodInvoker et Action, car ils encapsulent tous les deux un délégué qui ne prend pas de paragraphe et renvoie void
Si vous regardez leurs définitions, vous verrez simplement ceci.
public delegate void MethodInvoker();
public delegate void Action();
en outre, vous pouvez également écrire votre deuxième ligne sous la forme.
Control.BeginInvoke(new MethodInvoker(DoSomething), null);
C'est une question de préférence dans la plupart des cas, sauf si vous avez l'intention de réutiliser la méthode DoSomething (). De plus, les fonctions anonymes placeront vos variables étendues sur le tas, ce qui pourrait en faire une fonction plus coûteuse.
N'oubliez pas de vérifier si le contrôle est disponible pour le moment, pour éviter les erreurs lors de la fermeture du formulaire.
if(control.IsHandleCreated)
control.BeginInvoke((MethodInvoker)(() => control.Text="check123"));