繁体   English   中英

输入参数的Control.Invoke

[英]Control.Invoke with input Parameters

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

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

使用C#3.5
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());

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

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;
    }
  }
}

使用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<YourType>(() => 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});

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

使用:动作(STARS db)

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

我认为,Samuel的(优秀)方法可以进一步推广:

扩展方式:

public static void ExecuteAsync<TControl>(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.
  });
}
    private void ppTrace(string tv)
    {
        if (_Txb1.InvokeRequired)
        {
            _Txb1.Invoke((Action<string>)ppTrace, tv);
        }
        else
        {
            _Txb1.AppendText(tv + Environment.NewLine);
        }
    }

找到了一个优雅的.net 2.0方法,并在MethodInvoker委托中包装了匿名方法。 这样就无需一直定义自己的委托。 例:

    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);
}));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM