如何使用BeginInvoke C#

64

你能为我解释一下这个吗:

someformobj.BeginInvoke((Action)(() =>
{
    someformobj.listBox1.SelectedIndex = 0;
}));
你能告诉我如何确切地使用begininvoke吗? Action类型是什么? 为什么有空白的括号()? 这个=>是什么意思?

3
一个帖子中有这么多不同的问题...应该至少分成三个独立的问题。 - Prokurors
1
请查看这篇文章:http://mark-dot-net.blogspot.com.uy/2014/07/six-ways-to-initiate-tasks-on-another.html - NoWar
2个回答

91

Action 是.NET框架提供的一种委托类型。 Action 指向一个无参数且不返回值的方法。

() =>lambda表达式语法。Lambda表达式不是Delegate类型。调用需要Delegate,因此可以使用Action来包装lambda表达式并为Invoke()提供预期的类型。

Invoke会使所述Action在创建控件的窗口句柄的线程上执行。更改线程通常是必要的以避免异常。例如,如果尝试在需要调用Invoke时在RichTextBox上设置Rtf属性而没有先调用Invoke,则会引发“跨线程操作无效”异常。在调用Invoke之前,请检查Control.InvokeRequired

BeginInvokeInvoke的异步版本。异步意味着线程不会阻塞调用者,而同步调用则是阻塞的。


所以如果我理解正确,Action用于保证跨线程安全性,因此您将通过方法调用通知对象而不是自己设置值?此外,该方法将接受任何委托,而不仅仅是特定的Action,是吗? - Kyle Baran
4
“Action”与线程安全无关,这与“Invoke”不同。 “Invoke”接受一个“Delegate”作为参数。因此,任何可以转换为“Delegate”的东西都可以作为参数传递。 - P.Brian.Mackey
@KyleBaran Action只是内置的委托类型,你可以用下面代码替换它: delegate void mydlg(); Invoke((mydlg)(() => { })); - im_chc

15

我猜您的代码与Windows Forms有关。
如果需要在UI线程异步执行某些操作(通常是更改控件属性),则可以调用BeginInvoke方法。
粗略地说,这是通过将委托传递给某个定期执行的过程(消息循环处理等)来实现的。

如果为Delegate类型调用BeginInvoke方法,则委托仅被异步调用。(同步版本使用Invoke方法。)

如果您想要更通用的代码,可以考虑使用Task Parallel Library,并使用相应的上下文TaskScheduler.FromCurrentSynchronizationContext())运行Task

另外,正如其他人所说,Lambda可以被视为匿名方法或表达式。这就是为什么您不能仅使用var来声明一个Lambda表达式:编译器需要提示。

更新:

这需要.NET v4.0及更高版本。

// This line must be called in UI thread to get correct scheduler
var scheduler = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext();

// this can be called anywhere
var task = new System.Threading.Tasks.Task( () => someformobj.listBox1.SelectedIndex = 0);

// also can be called anywhere. Task  will be scheduled for execution.
// And *IF I'm not mistaken* can be (or even will be executed synchronously)
// if this call is made from GUI thread. (to be checked) 
task.Start(scheduler);
如果您在其他线程中启动任务并需要等待其完成,task.Wait() 将阻止调用线程直到任务结束。
了解有关任务的更多信息,请单击此处

1
请给我一些例子好吗? - Mohammed Noureldin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接