我正在使用Windows窗体应用程序,它包含自定义控件,其中的方法可能会从UI线程以外的线程调用。因此,这些方法看起来有点像这样以防止例外:
public void DoSomeStuff()
{
if (InvokeRequired)
{
Invoke((Action)DoSomeStuff);
}
else
{
// Actually do some stuff.
}
}
方法组DoSomeStuff
对Action
的明确演员引起了我的注意,所以我一直在深入研究代表和其他相关主题。
虽然我在这里看到了一些相关的问题,但我还是找不到我的答案,这是:
为什么方法组DoSomeStuff
在这种情况下需要显式转换为Action
?
如果我删除演员表,那么我会收到两个错误:
错误102参数1:无法从'方法组'转换为 'System.Delegate'
错误101最佳重载方法匹配 'System.Windows.Forms.Control.Invoke(System.Delegate,params object [])'有一些无效的参数
编译器显然对使用Invoke
的哪个重载感到困惑这一事实似乎是一个相当大的提示,但我仍然不确定为什么它无法解决这个问题。我希望编译器推断出Invoke
的第一个重载,它需要一个Delegate
参数,应该使用它。
我希望如果代码是这样编写的话没有问题:
Action a = DoSomeStuff;
Invoke(a);
方法组DoSomeStuff
可以隐式转换为Action
委托类型,Action
从System.Delegate
派生(技术上?),因此Invoke
可以处理参数a
没有任何麻烦。但是当我尝试直接传递DoSomeStuff
作为参数时,为什么编译器无法进行隐式转换?说实话,我不相信我自己的逻辑,但我仍然不确定我错过了什么。
答案 0 :(得分:3)
问题不在于编译器在选择过载时遇到问题。 “最佳匹配”重载是您想要的,但它具有无效参数。 C#语言未定义从方法组(DoSomeStuff
)到System.Delegate
的任何隐式转换。
您可能会说编译器应该选择Action
/ Func
类型中的一种,并且已将其作为语言功能请求。现在这不是C#的一部分。 (我不知道为什么;我希望语言请求能够通过。)
System.Windows.Forms.Control.Invoke
是在.NET 1.0中创建的。今天,人们将使用以下签名:
void Invoke(Action action);
Task InvokeAsync(Action action);
它只会起作用。
尝试迁移到await
,这不再是一个问题。