下面的选项 1 和选项 2 有什么区别?
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() 似乎使用:
this.FindMarshalingControl().MarshaledInvoke(this, method, args, 1);
似乎最终调用了一些像 PostMessage() 这样的 native 函数,无法完全弄清楚反射器的流程(讨厌的编译器转到优化)
而 BackgroundWorker.Invoke() 似乎使用:
this.asyncOperation.Post(this.progressReporter, args);
这似乎最终会调用 ThreadPool.QueueUserWorkItem()
(我只是猜测这些是每种情况的相关函数调用。)如果我理解正确,使用 ThreadPool 不能保证执行顺序,而使用 Post 机制可以。也许这会是一个潜在的差异? ( 编辑 - 我无法综合这种情况 - 在这两种情况下似乎都保留了调用顺序,至少在我的简单测试中。)
谢谢!
最佳答案
他们都是一样的。您在 BackgroundWorker
中看到的调用使用 SynchronizationContext
。 Post()
方法的默认实现确实使用线程池,但是在启动 Windows 窗体应用程序时,默认同步上下文被 WindowsFormsSynchronizationContext
替换,它实际上调用 Control.BeginInvoke()
。
关于winforms - BackgroundWorker.ReportProgress() 和 Control.BeginInvoke() 的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2865971/