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

时间:2011-09-09 11:10:29

标签: c# outlook backgroundworker

我正在编写一个outlook的插件,它有一些API调用的网络代码,这就是为什么我有几个扩展BackgroundWorker类的类,每个类封装一个API调用。对于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);
    }
}

对于我的Outlook Addin,代码看起来像这样:

public class ThisAddin
{

    private ApiLogin _loginWorker;

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

当我运行我的插件时,由于我在后台工作程序完成事件处理程序中有一个Thread.Sleep(50000),因此我希望outlook可以阻止50秒,但这不会发生。这对我来说意味着这段代码不能在主线程中运行?我一直在寻找一个徒劳的解决方案,现在我想知道这里是否有人知道这可能是什么问题?

2 个答案:

答案 0 :(得分:3)

BackgroundWorker需要同步提供程序来确定RunWorkerCompleted事件在哪个线程上运行。它使用SynchronizationContext.Current。插件启动时,此属性为null的可能性非常高。所以什么都没有得到同步,事件在线程池线程上运行。

.NET框架中有两个同步提供程序,分别是Winforms和WPF的一个。他们需要各自的消息循环来执行线程编组,他们在Application.Run()方法中分配SynchronizationContext.Current。你没有。最简单的解决方案是创建Winforms表单并调用其ShowDialog()方法。这本身已经阻止了Outlook用户界面。也很好地向用户提供一些反馈,因此她不必猜测Outlook停止响应的原因。

答案 1 :(得分:1)

我当然希望它在与ThisAddinStartup方法相同的线程上运行:您可以通过在两个位置跟踪线程ID来验证这一点。

至于Outlook,也许它在一个单独的UI线程上运行你的加载项。