3

我有一个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. 

谢谢你。

4

4 回答 4

4

通常使用 Winforms/WPF,如果您需要与长时间运行的任务中的 UI 交互,您可以使用 Invoke() 跳转到 UI 线程。您可以从属于 UI 的任何对象调用调用,但请确保在调用范围内时只执行尽可能少的代码。由于此代码位于 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);
        });
    }
}
于 2012-10-04T04:24:18.127 回答
4

您不应尝试从后台线程与任何 UI 组件进行交互。

一种方法可能是在 doWork 方法中捕获异常并将其分配给后台工作人员的 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
    }
}
于 2012-10-04T03:51:33.567 回答
3

您必须使用此方法

 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);
        }

    }
于 2015-02-15T19:28:05.603 回答
3

您的后台线程只是一个工作线程,而不是用户界面线程。WPF 和 WinForms 都要求将执行用户界面操作的线程标记为 STA(单线程单元),因为用户界面代码不是线程安全的。它们还要求您添加消息泵,以便发送 Windows 消息。

我建议不要在工作线程中显示消息框,而是向主用户界面线程发送消息并让该线程显示消息框。为此,您应该将对 Dispatcher 的引用从主 UI 线程传递到工作线程。然后使用 Dispatcher.BeginInvoke 请求在主线程上回调委托。

或者,您可以等待后台线程完成,然后检查结果并向用户显示适当的答案。无论哪种方式,工作线程都不应该直接与用户界面交互。

于 2012-10-04T03:51:10.087 回答