//Process is a method, invoked as a method group
Dispatcher.Current.BeginInvoke((Action) Process);
//or use an anonymous method
Dispatcher.Current.BeginInvoke((Action)delegate => {
SomeFunc();
SomeOtherFunc();
});
// Create delegates for the different return types needed.
private delegate void VoidDelegate();
private delegate Boolean ReturnBooleanDelegate();
private delegate Hashtable ReturnHashtableDelegate();
// Now use the delegates and the delegate() keyword to create
// an anonymous method as required
// Here a case where there's no value returned:
public void SetTitle(string title)
{
myWindow.Invoke(new VoidDelegate(delegate()
{
myWindow.Text = title;
}));
}
// Here's an example of a value being returned
public Hashtable CurrentlyLoadedDocs()
{
return (Hashtable)myWindow.Invoke(new ReturnHashtableDelegate(delegate()
{
return myWindow.CurrentlyLoadedDocs;
}));
}
// Thread-safe update on a form control
public void DisplayResult(string text){
if (txtResult.InvokeRequired){
txtResult.Invoke((Action)delegate {
DisplayResult(text);
});
return;
}
txtResult.Text += text + "\r\n";
}
9条答案
按热度按时间afdcj2ne1#
因为
Invoke
/BeginInvoke
接受Delegate
(而不是类型化委托),所以需要告诉编译器要创建什么类型的委托;MethodInvoker
(2.0)或Action
(3.5)是常见的选择(注意它们具有相同的签名);像这样:如果你需要传入参数,那么"捕获变量"就是这样:
(警告:如果使用捕获 * async *,您需要谨慎一点,但 * sync * 是可以的-即上面的方法是可以的)
另一种选择是编写一个扩展方法:
然后:
当然,您可以对
BeginInvoke
执行相同的操作:如果你不能使用C#3.0,你可以用一个常规的示例方法做同样的事情,大概在
Form
基类中。gg58donl2#
实际上你不需要使用delegate关键字,只要传递lambda作为参数即可:
wvmv3b1j3#
rlcwz9us4#
你需要创建一个委托类型。在匿名方法创建中的关键字“delegate”有点误导。你不是在创建匿名委托,而是在创建匿名方法。你创建的方法可以在委托中使用。如下所示:
jutyujz05#
为了完整起见,这也可以通过Action方法/匿名方法组合来完成:
3df52oht6#
我对其他建议有疑问,因为我有时候想从我的方法返回值。如果你尝试使用带返回值的MethodInvoker,它似乎不喜欢它。所以我使用的解决方案是这样的(很高兴听到一种方法,使其更简洁-我使用的是c#.net 2.0):
wbgh16ku7#
我喜欢用Action代替MethodInvoker,它更短,看起来更干净。
例如:
s1ag04yj8#
我一直不明白为什么这会对编译器产生影响,但这已经足够了。
额外的好处:添加一些错误处理,因为如果您从后台线程使用
Control.Invoke
,您很可能正在更新控件的text / progress / enabled状态,而不关心控件是否已经被释放。l2osamch9#
我需要它来显示来自一个单独线程的模态对话框,但在某种程度上,我实际上也可以从它获得一个返回值。Vokinneberg's answer使我走上了正确的道路,但我仍然需要更多的东西。
我想到的最后一个解决方案是添加以下内容,作为
MethodInvoker
的函数版本:现在,如果我有一个像这样的函数,它显示一个模态对话框并从中返回数据...
...它可以从不同的线程调用,如下所示:
现在,一切正常:在主窗体上调用函数,对话框显示为主窗体的模态对话框,并且将来自对话框的值返回到可继续其处理的另一线程。
这里仍然有一些丑陋的强制转换,因为
Control.Invoke
碰巧返回了一个Object,但是它仍然可以用于任何函数,只要不涉及像输出参数这样的高级东西。如果我使用泛型的话,也许可以把它做得更干净,比如
Form
上的扩展方法或者其他什么,在内部进行强制转换,但是现在,这样就可以了。