调用和开始调用

发布于 2024-08-14 16:03:03 字数 858 浏览 9 评论 0原文

问候, 我正在用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

很酷不放纵 2024-08-21 16:03:03

首先,从您的链接:

  • Control.Invoke:在 UI 线程上执行,但调用线程在继续之前等待完成。
  • Control.BeginInvoke:在异步UI线程上执行,调用线程不等待完成。

以及来自 MSDN 的信息:

BeginInvoke 在创建控件的基础句柄的线程上异步执行指定的委托。

总而言之,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:

BeginInvoke executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.

To sum it up, BeginInvoke is asynchronous. When BeginInvoke 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.

遗忘曾经 2024-08-21 16:03:03

通过 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!

雨的味道风的声音 2024-08-21 16:03:03

Control.BeginInvoke 不能在不同的线程(或线程池)上工作,而 delegate.BeginInvoke 可以。 MSDN 的一篇文章说:

执行指定的委托
在线程上异步执行
控件的底层句柄是
创建于。

但是 Control.BeginInvoke 只是使用 PostMessage 并返回 - 没有创建 CLR Thread

PostMessage函数放置
(发布)消息队列中的消息
与该线程相关联
创建了指定的窗口并
不等待线程就返回
处理消息。

本文总结了是使用 Invoke 还是 BeginInvoke 很好:

您问要使用哪个函数。它
真的取决于你的要求。如果
您希望完成 UI 更新
在继续之前,您可以使用 Invoke。如果
没有这样的要求,我会
建议使用 BeginInvoke,因为它使得
线程似乎调用它
“快点”。有一些问题
不过用 BeginInvoke 。

  • 如果您通过 BeginInvoke 调用的函数访问共享状态
    (UI 线程之间共享状态
    和其他线程),你在
    麻烦。状态可能会改变
    在你打电话的时间之间
    BeginInvoke 和何时包装
    函数实际执行,导致
    很难发现时序问题。
  • 如果您将引用参数传递给通过以下方式调用的函数
    BeginInvoke,那么你必须确保
    没有其他人修改通过的
    函数完成之前的对象。
    通常,人们克隆该对象
    在将其传递给 BeginInvoke 之前,
    这完全避免了这个问题。

Control.BeginInvoke doesn't work on a different thread (or threadpool), a delegate.BeginInvoke does. MSDN's one liner says:

Executes the specified delegate
asynchronously on the thread that the
control's underlying handle was
created on.

However Control.BeginInvoke simply uses PostMessage and returns - no CLR Thread is created.

The PostMessage function places
(posts) a message in the message queue
associated with the thread that
created the specified window and
returns without waiting for the thread
to process the message.

This article summarises whether to use Invoke or BeginInvoke quite well:

Which function to use, you ask. It
really depends on your requirement. If
you want your UI update to complete
before proceeding, you use Invoke. If
there is no such requirement, I'd
suggest using BeginInvoke, as it makes
the thread calling it seemingly
"faster". There are a few gotcha's
with BeginInvoke though.

  • If the function you are calling via BeginInvoke accesses shared state
    (state shared between the UI thread
    and other threads), you are in
    trouble. The state might change
    between the time you called
    BeginInvoke and when the wrapped
    function actually executes, leading to
    hard to find timing problems.
  • If you are passing reference parameters to the function called via
    BeginInvoke, then you must make sure
    that no one else modifies the passed
    object before the function completes.
    Usually, people clone the object
    before passing it to BeginInvoke,
    which avoids the problem altogether.
喜你已久 2024-08-21 16:03:03

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.

三人与歌 2024-08-21 16:03:03

这基本上可以归结为您是否希望控件同步或异步更新。这一切都取决于您的具体情况。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文