[英]BackgroundWorker thread must be STA
我有一个BackgroundWorker调用函数在BackgroundWorker _DoWork上执行一个很长的过程,当函数出错时我会提示自定义的消息框:
WPFMessageBoxResult result = WPFMessageBox.Show("Activation Fail", "Error!!", WPFMessageBoxButtons.OK, WPFMessageBoxImage.Error);
以下例外发生在WPFMessageBoxResult类:
The calling thread must be STA, because many UI components require this.
谢谢。
您不应尝试与后台线程中的任何UI组件进行交互。
一种方法是在doWork方法中捕获异常并将其分配给backgroundworker的result属性,然后检查该结果是否是一种异常,如果您没有将结果用于其他任何内容,则不为null。 然后在backgroundWorker_completed事件中检查它。
BackgroundWorker_DoWork(sender, )
{
try
{
// do work
}
catch (Exception ex)
{
BackgroundWorker w = sender as BackgroundWorker;
if (w != null)
w.Result = ex;
}
}
然后
BackgroundWorker_Completed()
{
if (s.Result != null && e.Result is Exception)
{
Exception ex = e.Result as Exception;
// do something with ex
}
}
通常使用Winforms / WPF,如果需要从长时间运行的任务中与UI进行交互,则使用Invoke()跳转到UI线程。 您可以从属于UI的任何对象调用invoke,但要确保在调用范围内只执行尽可能少的代码。 由于此代码位于UI线程上,因此如果需要太长时间,它将阻止/挂起UI。
public void BackgroundWorkerMethod()
{
try
{
// do work
}
catch (Exception e)
{
uiObject.Invoke(new Action(() => {
// now you are on the UI thread
Message.ShowMessage(e.Message);
});
}
}
您的后台线程只是一个工作线程而不是用户界面线程。 WPF和WinForms都要求执行用户界面操作的线程被标记为STA(单线程单元),因为用户界面代码不是线程安全的。 它们还要求您添加消息泵以便分派Windows消息。
我建议您不要在工作线程中显示消息框,而是向主用户界面线程发送消息并让该线程显示消息框。 为此,您应该将Dispatcher的引用从主UI线程传递到工作线程。 然后使用Dispatcher.BeginInvoke请求在主线程上回调委托。
或者,您可以等待后台线程完成,然后检查结果并向用户显示相应的答案。 无论哪种方式,工作线程都不应该直接与用户界面交互。
您必须使用此方法
void BGW_DoWork(object sender, DoWorkEventArgs e)
{
try
{
Dispatcher.BeginInvoke(new Action(() =>
{
Button btn = new Button();
btn.Width = 100;
btn.Height = 50;
btn.Content = "Test";
myG.Children.Add(btn);
}
));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.