如何使用 BeginInvoke C#

Posted

技术标签:

【中文标题】如何使用 BeginInvoke C#【英文标题】:How to use BeginInvoke C# 【发布时间】:2013-01-01 12:38:21 【问题描述】:

您能帮我解释一下吗:

someformobj.BeginInvoke((Action)(() =>

    someformobj.listBox1.SelectedIndex = 0;
));

您能告诉我如何准确地使用begininvoke 吗? 什么是Action 类型? 为什么有空括号()=> 是什么意思?

【问题讨论】:

一篇文章中有这么多不同的问题...... - 应该至少有 3 个单独的问题 也看看这篇文章mark-dot-net.blogspot.com.uy/2014/07/… 【参考方案1】:

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

() => 是 lambda expression 语法。 Lambda 表达式不属于 Delegate 类型。调用需要Delegate,因此Action 可用于包装lambda 表达式并将预期的Type 提供给Invoke()

Invoke 导致Action 在创建控件窗口句柄的线程上执行。通常需要更改线程以避免Exceptions。例如,如果在需要调用时尝试在RichTextBox 上设置Rtf 属性,而无需先调用Invoke,则将引发Cross-thread operation not valid 异常。在调用 Invoke 之前检查 Control.InvokeRequired

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

【讨论】:

所以如果我理解正确的话,Action是用来保证跨线程安全的,所以你会通过方法调用通知对象而不是自己设置值?此外,该方法将接受任何委托,而不仅仅是具体的 Action,是吗? @KyleBaran - Action 与线程安全无关,即InvokeInvoke 接受 Delegate 作为参数。所以任何可转换为Delegate 的东西都可以作为参数传递。 @KyleBaran Action 只是一个内置的委托类型,您可以将其替换为:delegate void mydlg();调用((mydlg)(() => ));【参考方案2】:

我猜您的代码与 Windows 窗体有关。 如果您需要在 UI 线程中异步执行某些内容,请调用 BeginInvoke:在大多数情况下更改控件的属性。 粗略地说,这是通过将委托传递给某个定期执行的过程来完成的。 (消息循环处理之类的东西)

如果为Delegate 类型调用BeginInvoke,则委托只是异步调用。 (Invoke 用于同步版本。)

如果您想要更多适用于 WPF 和 WinForms 的通用代码,您可以考虑使用任务并行库并运行 Task 和相应的 context。 (TaskScheduler.FromCurrentSynchronizationContext())

在其他人已经说过的基础上再补充一点: Lambda 可以被视为匿名方法或expressions。 这就是为什么您不能只将 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() 将阻塞调用线程直到任务结束。

阅读更多关于任务here。

【讨论】:

你能给我一些例子吗?

以上是关于如何使用 BeginInvoke C#的主要内容,如果未能解决你的问题,请参考以下文章

C#中的invoke和begininvoke

c#的BeginInvoke和EndInvoke使用demo

c# 从delegate.begininvoke 捕获异常而不调用delegate.endinvoke

C#异步调用四大方法详解

C#如何使用异步编程

C# 多线程 Invoke BeginInvoke