首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >BackgroundWorker.ReportProgress()和Control.BeginInvoke()之间的区分

BackgroundWorker.ReportProgress()和Control.BeginInvoke()之间的区分
EN

Stack Overflow用户
提问于 2010-05-19 13:39:03
回答 3查看 1.8K关注 0票数 3

以下选项1和2的区别是什么?

代码语言:javascript
运行
复制
    private void BGW_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i=1; i<=100; i++)
        {
            string txt = i.ToString();
            if (Test_Check.Checked)
                //OPTION 1
                Test_BackgroundWorker.ReportProgress(i, txt); 
            else
                //OPTION 2
                this.BeginInvoke((Action<int, string>)UpdateGUI, 
                                  new object[] {i, txt});
        }
    }

    private void BGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        UpdateGUI(e.ProgressPercentage, (string)e.UserState);
    }

    private void UpdateGUI(int percent, string txt)
    {
        Test_ProgressBar.Value = percent;
        Test_RichTextBox.AppendText(txt + Environment.NewLine);
    }

在反光镜中,Control.BeginInvoke()似乎使用:

代码语言:javascript
运行
复制
this.FindMarshalingControl().MarshaledInvoke(this, method, args, 1);

它似乎最终调用了一些本机函数,如PostMessage(),但无法准确地计算出来自反射器的流(烦人的编译器转到优化)。

而BackgroundWorker.Invoke()似乎使用:

代码语言:javascript
运行
复制
this.asyncOperation.Post(this.progressReporter, args);

它似乎最终调用了ThreadPool.QueueUserWorkItem()

(我只是猜测这是每个案例的相关函数调用。)如果我正确理解,使用ThreadPool并不能保证执行顺序,而使用Post机制则会保证执行顺序。也许这是一个潜在的区别?(编辑--我无法综合这样的情况--至少在我的简单测试中,这两种情况下调用顺序似乎都保持不变。)

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-05-20 12:31:45

他们俩是一样的。您在BackgroundWorker中看到的电话使用SynchronizationContext。实际上,Post()方法的默认实现使用线程池,但是在启动Windows应用程序时,默认的同步上下文被WindowsFormsSynchronizationContext所取代,后者实际上调用了Control.BeginInvoke()

票数 2
EN

Stack Overflow用户

发布于 2010-05-19 13:46:01

一个很大的区别是Control.Invoke会阻塞直到UpdateGUI调用被执行和完成,而BackgroundWorker.ReportProgress不会阻塞(在BackgroundWorker引发事件之前,它会立即返回)。

如果希望它们的行为相同,则调用Control.BeginInvoke (而不是阻塞)。

票数 2
EN

Stack Overflow用户

发布于 2010-07-04 10:03:04

我发现了一个很大的区别。在BGW运行时关闭表单将导致this.Invoke()和this.BeginInvoke()抛出一个ObjectDisposedException。BGW的ReportProgress机制绕过了这一点。为了享受这两个世界的最佳状态,下面的模式工作得很好

代码语言:javascript
运行
复制
public partial class MyForm : Form
{
    private void InvokeViaBgw(Action action)
    {
        Packing_Worker.ReportProgress(0, action);
    }

    private void BGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        if (this.IsDisposed) return; //You are on the UI thread now, so no race condition

        var action = (Action)e.UserState;
        action();
    }

    private private void BGW_DoWork(object sender, DoWorkEventArgs e)
    {
       //Sample usage:
       this.InvokeViaBgw(() => MyTextBox.Text = "Foo");
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2865971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档