我在堆栈溢出上搜索了调用所需的相关帖子的高低..它帮助我学到了很多..但我有几个问题..不仅与调用所需有关,还与后台工作人员有关..请多多包涵.. :)
我的应用程序做了一些很长的事情,需要在进程中更新 gui(进度条、状态栏、文本框)。我使用了一个线程,但是在更新 UI 时它给出了可怕的跨线程异常。我最近(有点)掌握了正确使用invokerequired的窍门..[自动化InvokeRequired代码模式]..我在这篇文章中使用的代码是:
public static partial class CHelper
{
public static void InvokeIfRequired(this Control oCtrl, MethodInvoker fnAction)
{
if (oCtrl.InvokeRequired)
{
oCtrl.Invoke(fnAction);
}
else
{
fnAction();
}
}
}
public partial class Form1 : Form
{
public void Test()
{
this.InvokeIfRequired(() =>
{
Text = "Window Title";
button1.Text = "Hello";
});
button1.InvokeIfRequired(() =>
{
Text = "Window Title";
button1.Text = "Hello";
});
}
}
现在这是我注意到的事情.. this.InvokeIfRequired 和 button1.InvokeIfRequired 都做同样的事情.. 为什么会这样?我期待 button1.InvokeIfRequired 中的 Text 对应于 button1 的 text 属性.. 但它指的是父表单的.. 对我来说这似乎很愚蠢、不直观和错误.. 或者我做错了什么..
另一个问题..当时我没有掌握invokerequired的窍门,所以我求助于使用后台工作者..并使用进度事件来更新gui..
public partial class Form1 : Form
{
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.ReportProgress(0, "Hello World");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.UserState != null)
{
button1.Text = e.UserState as string;
}
}
}
到目前为止,它还没有给我带来问题..我想知道这两种方法中哪一种更好?为什么?另外,有没有办法将数据传递给之前的 InvokeIfRequired 函数?
谢谢.. =)
编辑 01:对父窗体或目标控件使用 Invoke 有什么区别吗?.. 是的 form.invoke 和 control.invoke 是一样的.. 但为什么会这样呢?它不直观,并给人以错误的印象..