带输入参数的Control.Invoke

Ada*_*ile 13 c# multithreading winforms

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

Sam*_*uel 22

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

用C#3.5
public static class ControlExtensions
{
  public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                             Func<TControl, TResult> func)
    where TControl : Control
  {
    return control.InvokeRequired
            ? (TResult)control.Invoke(func, control)
            : func(control);
  }

  public static void InvokeEx<TControl>(this TControl control,
                                        Action<TControl> func)
    where TControl : Control
  {
    control.InvokeEx(c => { func(c); return c; });
  }

  public static void InvokeEx<TControl>(this TControl control, Action action)
    where TControl : Control
  {
    control.InvokeEx(c => action());
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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());
Run Code Online (Sandbox Code Playgroud)
使用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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

this.UpdateControlText(label1, "Hello world");
Run Code Online (Sandbox Code Playgroud)


Den*_*s T 7

更多可能性:

this.Invoke(new MethodInvoker(() => this.DoSomething(param1, param2)));
Run Code Online (Sandbox Code Playgroud)

要么

this.Invoke(new Action(() => this.DoSomething(param1, param2)));
Run Code Online (Sandbox Code Playgroud)

甚至

this.Invoke(new Func<YourType>(() => this.DoSomething(param1, param2)));
Run Code Online (Sandbox Code Playgroud)

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


Tim*_*Tim 6

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

例如,在一个表格中:

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

public DelegatePassMessages passMessage;
Run Code Online (Sandbox Code Playgroud)

在构造函数中:

passMessage = new DelegatePassMessages (this.MessagesIn);
Run Code Online (Sandbox Code Playgroud)

然后MessagesIn函数接收数据:

public void MessagesIn(string name, int value)
{

}
Run Code Online (Sandbox Code Playgroud)

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

formName.Invoke(formName.passMessage, new Object[] { param1, param2});
Run Code Online (Sandbox Code Playgroud)