解释委托调用的语法c#

时间:2012-04-20 20:40:35

标签: c# multithreading delegates

在此链接的代码中: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;
 }
}

4 个答案:

答案 0 :(得分:4)

TL; DR:

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

//

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

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获取一个对象数组,它将用作给定委托的args。 (是的,您的更新方法需要一个字符串arg,请继续阅读)使用变量del,您可以自己调用updateLabelText

del(newText);

基本上与以下内容相同:

updateLabelText(newText);

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

编辑我对科学进行了深入挖掘,invocation内部更像是:

del.DynamicInvoke(args);

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

实际上,不需要显式创建数组,并且

label1.Invoke(del, newText)

也有效。

答案 3 :(得分:1)

首先,值得注意的是,这并未在代理上调用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[]的值是允许各种情况的最佳方式。