带输入参数的Control.Invoke

根据我在C#中发现的内容,Control.Invoke方法要求您使用没有输入参数的委托。 有没有办法解决? 我想调用一个方法来从另一个线程更新UI并将字符串参数传递给它。

您使用的是哪个版本的C#? 如果您使用的是C#3.5,则可以使用闭包来避免传入参数。

用C#3.5

public static class ControlExtensions { public static TResult InvokeEx(this TControl control, Func func) where TControl : Control { return control.InvokeRequired ? (TResult)control.Invoke(func, control) : func(control); } public static void InvokeEx(this TControl control, Action func) where TControl : Control { control.InvokeEx(c => { func(c); return c; }); } public static void InvokeEx(this TControl control, Action action) where TControl : Control { control.InvokeEx(c => action()); } } 

安全地调用代码现在变得微不足道。

 this.InvokeEx(f => f.label1.Text = "Hello World"); this.InvokeEx(f => this.label1.Text = GetLabelText("HELLO_WORLD", var1)); this.InvokeEx(() => this.label1.Text = DateTime.Now.ToString()); 

使用C#2.0,它变得不那么琐碎了

 public class MyForm : Form { private delegate void UpdateControlTextCallback(Control control, string text); public void UpdateControlText(Control control, string text) { if (control.InvokeRequired) { control.Invoke(new UpdateControlTextCallback(UpdateControlText), control, text); } else { control.Text = text; } } } 

使用它很简单,但您必须为更多参数定义更多回调。

 this.UpdateControlText(label1, "Hello world"); 

更多可能性:

 this.Invoke(new MethodInvoker(() => this.DoSomething(param1, param2))); 

要么

 this.Invoke(new Action(() => this.DoSomething(param1, param2))); 

甚至

 this.Invoke(new Func(() => this.DoSomething(param1, param2))); 

第一个选项是最好的选项,因为MethodInvoker是为此目的而设想的,并且具有更好的性能。

正如卢克所说,使用Control.Invoke就像这样……

例如,在一个表格中:

 public delegate void DelegatePassMessages(string name, int value); public DelegatePassMessages passMessage; 

在构造函数中:

 passMessage = new DelegatePassMessages (this.MessagesIn); 

然后MessagesIn函数接收数据:

 public void MessagesIn(string name, int value) { } 

然后将数据传递到您的表单:

 formName.Invoke(formName.passMessage, new Object[] { param1, param2}); 

我认为塞缪尔(优秀)的方法可以推得更多:

扩展方法:

 public static void ExecuteAsync(this TControl control, Action action) where TControl : Control { new Thread(() => { control.Invoke(action); }) .Start(); } 

表格代码:

 private void doStuff() { this.ExecuteAsync(() => { // Do your stuff in a separate thread // but having full access to local or instance variables. // No (visible) threading code needs to be used here. }); } 

这里使用带有Invoke()扩展名+输入参数的lambda表达式。

使用:动作(STARS db)

 _ccb.GetImagerFRU_PartNbr().Invoke(new Action(dbase => _ccb.GetImagerFRU_PartNbr().Text = dbase.PartNumber(serial) ?? String.Empty), db); 

使用MethodInvoker委托中包含的匿名方法为.net 2.0找到了一种优雅的方法。 这样就不需要一直定义自己的代理。 例:

  private void InitUI(Guid id, string typename) { MethodInvoker inv = delegate{tvMatrix.Nodes[0].Nodes.Add(id.ToString(), typename);}; tvMatrix.Invoke(inv); } 

为什么不

 tvMatrix.Invoke((MethodInvoker) (() => { tvMatrix.Nodes[0].Nodes.Add(id.ToString(), typename); })); 
  private void ppTrace(string tv) { if (_Txb1.InvokeRequired) { _Txb1.Invoke((Action)ppTrace, tv); } else { _Txb1.AppendText(tv + Environment.NewLine); } }