简体   繁体   English

BackgroundWorker线程必须是STA

[英]BackgroundWorker thread must be STA

I have a BackgroundWorker to call a function to do a long process at BackgroundWorker _DoWork, when error occur in the function I will prompt a customized messagebox: 我有一个BackgroundWorker调用函数在BackgroundWorker _DoWork上执行一个很长的过程,当函数出错时我会提示自定义的消息框:

 WPFMessageBoxResult result = WPFMessageBox.Show("Activation Fail", "Error!!", WPFMessageBoxButtons.OK, WPFMessageBoxImage.Error);

The exception below happens at WPFMessageBoxResult class : 以下例外发生在WPFMessageBoxResult类:

The calling thread must be STA, because many UI components require this. 

Thank you. 谢谢。

You should not try to interact with any UI components from a background thread. 您不应尝试与后台线程中的任何UI组件进行交互。

One way could be to catch the exception in your doWork method and assign it to the backgroundworker's result property and then check if that result is a type of exception or not null if you are not using the result for anything else. 一种方法是在doWork方法中捕获异常并将其分配给backgroundworker的result属性,然后检查该结果是否是一种异常,如果您没有将结果用于其他任何内容,则不为null。 then check for it in the backgroundWorker_completed event. 然后在backgroundWorker_completed事件中检查它。

BackgroundWorker_DoWork(sender, )
{
    try
    {
       // do work        
    }
    catch (Exception ex)
    {
         BackgroundWorker w = sender as BackgroundWorker;
         if (w != null)
             w.Result = ex;
    }
}

then 然后

BackgroundWorker_Completed()
{
    if (s.Result != null && e.Result is Exception)
    {
       Exception ex = e.Result as Exception;
       // do something with ex
    }
}

Usually with Winforms/WPF you use Invoke() to jump onto the UI thread if you need to interact with the UI from a long-running task. 通常使用Winforms / WPF,如果需要从长时间运行的任务中与UI进行交互,则使用Invoke()跳转到UI线程。 You can call invoke from any object that belongs to the UI, but be sure when in the invoke scope to only do as little code as possible. 您可以从属于UI的任何对象调用invoke,但要确保在调用范围内只执行尽可能少的代码。 Since this code is on the UI thread it will block/hang the UI if it takes too long. 由于此代码位于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);
        });
    }
}

Your background thread is just a worker thread and not a user interface thread. 您的后台线程只是一个工作线程而不是用户界面线程。 WPF and WinForms both require that the thread performing user interface actions be marked as STA (Single Threaded Apartment) because the user interface code is not thread safe. WPF和WinForms都要求执行用户界面操作的线程被标记为STA(单线程单元),因为用户界面代码不是线程安全的。 They also require that you add a message pump so that windows messages are dispatched. 它们还要求您添加消息泵以便分派Windows消息。

I recommend that instead of showing the message box in your worker thread you send a message to your main user interface thread and have that thread show the message box. 我建议您不要在工作线程中显示消息框,而是向主用户界面线程发送消息并让该线程显示消息框。 To do this you should pass a reference to the Dispatcher from the main UI thread into the worker thread. 为此,您应该将Dispatcher的引用从主UI线程传递到工作线程。 Then use the Dispatcher.BeginInvoke to request a delegate be called back on the main thread. 然后使用Dispatcher.BeginInvoke请求在主线程上回调委托。

Alternatively you can wait for the background thread to complete and then check the result and show the appropriate answer to the user. 或者,您可以等待后台线程完成,然后检查结果并向用户显示相应的答案。 Either way the worker thread should not be directly interacting with the user interface. 无论哪种方式,工作线程都不应该直接与用户界面交互。

You must use this method 您必须使用此方法

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM