【问题标题】:Explain syntax of delegate invocation c#解释委托调用c#的语法
【发布时间】:2012-04-20 20:40:34
【问题描述】:

在此链接的代码中:http://c-sharp-programming.blogspot.com/2008/07/cross-thread-operation-not-valid.html,委托用于从工作线程更新文本框的值。

我基本上可以看到发生了什么,但是这行的语法具体是:

label1.Invoke(del, new object[] { newText });

让我很困惑。有人可以解释一下吗?当只有一个参数时,为什么我们要为委托使用一种新的对象数组语法?

完整代码:

delegate void updateLabelTextDelegate(string newText);
private void updateLabelText(string newText)
{
 if (label1.InvokeRequired)
 {
     // this is worker thread
     updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);
     label1.Invoke(del, new object[] { newText });
 }
 else
 {
     // this is UI thread
     label1.Text = newText;
 }
}

【问题讨论】:

  • 这是一个错误,label1.Invoke() 不是委托。写label1.Invoke(del, newText);
  • 他是说 label1.Invoke() 是代表吗?我没有读过那个。另外,很好地指出,由于 params,您可以在没有显式 object[] 的情况下使用单个参数。

标签: c# multithreading delegates


【解决方案1】:

TL;DR:

Control.Invoke 在您的委托上调用 DynamicInvoke,该委托接受一个参数对象数组来处理任何委托类型。

//

C# 中的关键字delegate 类似于指定函数指针的类型。您可以使用该 type 来传递特定签名的方法。在您的示例中,签名用于采用 1 个 arg(字符串)并且不返回任何内容(void)的方法。方法updateLabelText 匹配该信号。行:

updateLabelTextDelegate del = new updateLabelTextDelegate(updateLabelText);

只是全文的说法:

updateLabelTextDelegate del = updateLabelText;

然后,您可以将变量del(现在是指向方法updateLabelText 的指针)传递给Control.Invoke 方法。

label1.Invoke(del, new object[] { newText });

这要感谢paramsControl.Invoke 签名中使用,您甚至不必明确地说它是object[]

label1.Invoke(del, newText);

Invoke 接受一个对象数组,它将用作给定委托的参数。 (是的,您的更新方法需要一个字符串 arg,请继续阅读)使用您的变量 del,您可以自己调用 updateLabelText

del(newText);

基本上与以下内容相同:

updateLabelText(newText);

Control.Invoke 内部,他们正在调用您的del 方法,但是由于委托上的一些辅助方法,它没有知道它需要多少个参数。你会发现这样的东西:

编辑我为科学做了一些深入挖掘,invocation 内部更像:

del.DynamicInvoke(args);

其中argsobject[]。有关您可以使用委托变量(Delegate 类型)执行的操作的更多信息,请阅读更多信息here

【讨论】:

  • 感谢您的详细解答,非常感谢! :)
【解决方案2】:

如果您查看Control.Invoke 的方法签名,您会发现它需要params Object[] args。您可以传递 object[] args 或单个参数。

【讨论】:

    【解决方案3】:

    对象数组被传递给委托的Invoke 方法。在这种情况下,updateLabelTextDelegate 采用单个 string 参数,因此是数组中的单个元素。

    其实数组不需要显式创建,而且

    label1.Invoke(del, newText)
    

    也是有效的。

    【讨论】:

    • +1 表示没有使用new object[],但我要指出这只是一个选项,感谢params
    【解决方案4】:

    首先,值得注意的是,这不是在委托上调用Invoke,而是在控件上调用Invoke。现在,如果您查看这里使用的Control.Invoke 的签名,是这样的:

    public Object Invoke(
        Delegate method,
        params Object[] args
    )
    

    如果该方法采用一个特定的委托类型,它可以采用该委托的适当参数类型。在你的情况下,你的委托只接受一个参数,但假设我们想传入一个Action<string, string, int> - 使用上面非常通用的方法,我们可以这样做:

    control.Invoke(someDelegate, new object[] { "foo", "bar", 10 });
    

    所以答案是object[] 是为了提供通用性,因为委托类型也是通用的。这有点像MethodInfo.Invoke - 在编译时不知道有多少参数,object[] 类型的值是允许各种情况的最佳方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-04
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多