简体   繁体   English

BackgroundWorkerCompleted似乎没有在主线程中运行?

[英]BackgroundWorkerCompleted doesnt seem to run in main thread?

I'm writing a addin for outlook which has some network code for API calls, which is why I have several classes extending the BackgroundWorker class, each encapsulating a API call. 我正在为Outlook写一个插件,其中包含一些用于API调用的网络代码,这就是为什么我有几个扩展BackgroundWorker类的类,每个类都封装了一个API调用的原因。 The code looks like this for a Api Call: 对于Api调用,代码如下所示:

public class ApiLogin : BackgroundWorker
{
    private void ThisAddInStartup(object sender, EventArgs e)
    {
        this.DoWork += BgWorkerDoWork;
        this.RunWorkerCompleted += BgWorkerCompleted;
    }

    private void BgWorkerDoWork(object sender, DoWorkEventArgs e)
    {
        //Perform network call on the background thread
        var logged_in = ApiRequests.login();
        e.Result = logged_in;
    }

    //This should run in the main thread, no?
    private void BgWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        var logged_in = (bool)e.Result;

        //Do stuff in main thread, hopefully..

        //Investigate if this runs in the main thread since it should block Outlook, no?
        Thread.Sleep(50000);
    }
}

And the code looks like this for my Outlook Addin: 我的Outlook插件的代码如下所示:

public class ThisAddin
{

    private ApiLogin _loginWorker;

    private void ThisAddInStartup(object sender, EventArgs e)
    {
       _loginWorker = new ApiLogin();
       _loginWorker.RunWorkerAsync();
    }
}

When I run my addin I expect outlook to block for 50 seconds since I have a Thread.Sleep(50000) in the background workers Completed-event handler, but this does not happen. 当我运行外接程序时,由于在后台工作程序Completed-Event处理程序中有Thread.Sleep(50000),因此我希望Outlook会阻塞50秒,但这不会发生。 This implies to me that this code does not run in the main thread? 对我而言,这意味着该代码不会在主线程中运行吗? I have searched for a solution in vain and now I would like to know if anyone here knows what might be the problem? 我徒劳地寻找解决方案,现在我想知道这里是否有人知道可能是什么问题?

BackgroundWorker requires a synchronization provider to determine on which thread the RunWorkerCompleted event runs. BackgroundWorker需要同步提供程序来确定RunWorkerCompleted事件在哪个线程上运行。 It uses SynchronizationContext.Current. 它使用SynchronizationContext.Current。 Odds are very high that this property is null when your plugin starts. 插件启动时,此属性为null的可能性很高。 So nothing is getting synchronized and the event runs on a threadpool thread. 因此,没有任何东西同步,并且该事件在线程池线程上运行。

There are two synchronization providers in the .NET framework, respectively the one for Winforms and the one for WPF. .NET框架中有两个同步提供程序,分别是Winforms和WPF。 They need their respective message loop to do the thread marshaling, they assign SynchronizationContext.Current in their Application.Run() method. 他们需要各自的消息循环来进行线程封送处理,并在其Application.Run()方法中分配SynchronizationContext.Current。 You have neither. 你都没有 The simplest solution is to create a Winforms Form and call its ShowDialog() method. 最简单的解决方案是创建Winforms窗体并调用其ShowDialog()方法。 That in itself already blocks the Outlook user interface. 它本身已经阻塞了Outlook用户界面。 Also good to provide some feedback to the user so she doesn't have to guess why Outlook stopped responding. 还可以向用户提供一些反馈,因此她不必猜测Outlook为何停止响应。

I would certainly expect it to run on the same thread as the ThisAddinStartup method: you can verify this by tracing the thread id in both places. 我当然希望它与ThisAddinStartup方法在同一线程上运行:您可以通过在两个地方跟踪线程ID来验证这一点。

As for Outlook, maybe it's running your add-in on a separate UI thread. 至于Outlook,也许它是在单独的UI线程上运行您的加载项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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