调用和开始调用
问候, 我正在用 C# 开发一些应用程序。目前我正在处理线程,我脑子里有一个问题。 Invoke 和 BeginInvoke 有什么区别? 我读了一些帖子,在这里找到了一些有用的信息:这里
但是以下代码中的 Invoke 和 BeginInvoke 有什么区别:
private void ProcessRoutine()
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
this.Invoke(this.MyDelegate, nValue);
//this.BeginInvoke(this.MyDelegate, nValue);
}
MessageBox.Show("Counting complete!");
}
private void MessageHandler(int progress)
{
lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString();
progressBar1.Value = progress;
}
其中 MyDelegate 是对 MessageHandler 函数的引用。
我注意到使用 BeginInvoke lblStatus.Text 不会刷新,而使用 Invoke 会刷新标签。 另外我知道 Invoke 会等待其执行完成。 我感兴趣的最重要的案例是为什么在这种情况下刷新标签文本存在差异。
Greetings,
I am developing some application in C#. At the moment I'm dealing with threading and I have a question that I have in my mind.
What is the difference between Invoke and BeginInvoke?
I read some thread and I found some useful information here: here
However what is the difference between Invoke and BeginInvoke in the following code:
private void ProcessRoutine()
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
this.Invoke(this.MyDelegate, nValue);
//this.BeginInvoke(this.MyDelegate, nValue);
}
MessageBox.Show("Counting complete!");
}
private void MessageHandler(int progress)
{
lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString();
progressBar1.Value = progress;
}
where MyDelegate is a reference to MessageHandler function.
I noticed that using BeginInvoke lblStatus.Text is not refreshed where using Invoke refreshes the label.
Additionally I know that Invoke waits for its execution to complete.
The most important case I'm interested in is why there is a difference in refreshing label text in this case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
首先,从您的链接:
Control.Invoke
:在 UI 线程上执行,但调用线程在继续之前等待完成。Control.BeginInvoke
:在异步UI线程上执行,调用线程不等待完成。以及来自 MSDN 的信息:
总而言之,
BeginInvoke
是异步。当从 UI 线程调用BeginInvoke
时,请求将与 UI 线程并行执行。这意味着它可能要等到当前执行的方法返回后才能执行。因此,在这种情况下,文本框永远不会出现更新,因为 for 循环不会被中断,因为调用线程在继续之前不会等待此事件完成。或者,
Invoke
是同步。文本框将被更新,因为调用线程将等待调用完成后再继续执行。To begin, from your link:
Control.Invoke
: Executes on the UI thread, but calling thread waits for completion before continuing.Control.BeginInvoke
: Executes on the asynchronous UI thread, and calling thread doesn't wait for completion.and from MSDN:
To sum it up,
BeginInvoke
is asynchronous. WhenBeginInvoke
is called from the UI thread the request will be executed in parallel with the UI thread. Which means it may not execute until after the currently executing method has returned. So in this case the text box will never appear to update because the for loop will not be interrupted, as the calling thread will not wait for this event to be completed before continuing.Alternatively,
Invoke
is synchronous. The text box will be updated because the calling thread will wait for the call to complete before continuing execution.通过 Invoke,方法被执行,应用程序等待它完成。
使用 BeginInvoke,该方法被异步调用,并且应用程序在执行 BeginInvoke 中引用的方法时继续执行。
使用 BeginInvoke,您需要调用 EndInvoke 来获取使用 BeginIvnoke 执行的方法的结果。
您不应该在 BeginXXX 方法中更新 GUI 组件,因为它们在 GUI 线程的另一个线程中运行,这与您的 Invoke 方法相反。您无法在与 GUI 线程不同的线程中访问 GUI 组件。
希望这有帮助!
With Invoke the method gets executed and the application waits for it to complete.
With BeginInvoke the method is invoked Asychnronously and the application continues to execute while the method referenced in BeginInvoke is executed.
With BeginInvoke you need to call EndInvoke to get the results of the method you executed using BeginIvnoke.
You should not update GUI components in BeginXXX methods as they are run in another thread to the GUI thread, contrary to your Invoke method. You cannot access GUI components in a different thread to the GUI thread.
Hope this helps!
Control.BeginInvoke
不能在不同的线程(或线程池)上工作,而 delegate.BeginInvoke 可以。 MSDN 的一篇文章说:但是
Control.BeginInvoke
只是使用 PostMessage 并返回 - 没有创建 CLRThread
。本文总结了是使用
Invoke
还是BeginInvoke
很好:Control.BeginInvoke
doesn't work on a different thread (or threadpool), a delegate.BeginInvoke does. MSDN's one liner says:However
Control.BeginInvoke
simply uses PostMessage and returns - no CLRThread
is created.This article summarises whether to use
Invoke
orBeginInvoke
quite well:BeginInvoke 在另一个线程上执行方法体并允许当前线程继续。如果您尝试从另一个线程直接更新控件属性,它将引发异常。
BeginInvoke executes the method body on another thread and allows the current thread to continue. If you are trying to directly update a control property from another thread, it will throw an exception.
这基本上可以归结为您是否希望控件同步或异步更新。这一切都取决于您的具体情况。
This basically boils down to whether or not you want the control to be updated synchronously or asynchronously. This all depends on your specific situation.