C# 使用DoEvents在Outlook加载项中挂起“进度”对话框

C# 使用DoEvents在Outlook加载项中挂起“进度”对话框,c#,.net,outlook,add-in,doevents,C#,.net,Outlook,Add In,Doevents,背景: 我在Outlook加载项中使用一个简单的进度对话框来显示执行长操作时的进度。因为我无法在单独的线程中运行使用Outlook对象的代码,所以我无法实现更传统的后台工作进程。我的加载项一直正常工作,直到Outlook 2013,在某些情况下,我的进度对话框挂起。当我在VS调试器中运行外接程序并导致挂起,然后执行中断时,它似乎卡在DoEvents()行上,该行试图强制progressbar更新 我的问题: 有人能推荐一个更好的系统来显示上述限制的进度吗(长时间运行的代码必须在Outlook主线

背景:

我在Outlook加载项中使用一个简单的进度对话框来显示执行长操作时的进度。因为我无法在单独的线程中运行使用Outlook对象的代码,所以我无法实现更传统的后台工作进程。我的加载项一直正常工作,直到Outlook 2013,在某些情况下,我的进度对话框挂起。当我在VS调试器中运行外接程序并导致挂起,然后执行中断时,它似乎卡在DoEvents()行上,该行试图强制progressbar更新

我的问题:

有人能推荐一个更好的系统来显示上述限制的进度吗(长时间运行的代码必须在Outlook主线程中运行)。是否有更好的方法使进度对话框响应而不使用DoEvents()

下面的简单代码演示了我现在是如何做到这一点的。在对Outlook对象执行长操作的加载项代码中:

private void longRunningProcess()
{
    int max = 100;

    DlgStatus dlgstatus = new DlgStatus();
    dlgstatus.ProgressMax = max;
    dlgstatus.Show();

    for (int i = 0; i < max; i++)
    {
        //Execute long running code that MUST best run in the main (Outlook's) thread of execution...
        System.Threading.Thread.Sleep(1000); //for simulation purposes

        if (dlgstatus.Cancelled) break;
        dlgstatus.SetProgress("Processing item: " + i.ToString(), i);
    }
}

我可以通过以下步骤来实现这一点。自定义表单有一个progressbar,其样式设置为Marquee

我从中获得了常规方法,但发现我不需要使用所有自定义窗口句柄

private void btn_syncContacts_Click(object sender, RibbonControlEventArgs e)
{
     Thread t = new Thread(SplashScreenProc);
     t.Start();

     //long running code
     this.SyncContacts();

     syncingSplash.Invoke(new Action(this.syncingSplash.Close), null);
}

private SyncingContactsForm syncingSplash = new SyncingContactsForm();

internal void SplashScreenProc(object param)
{
    this.syncingSplash.ShowDialog();
}

请务必注意,表单不适用于Outlook对象模型。Microsoft不建议在单独的线程上使用对象模型。

为什么不能像处理其他UI应用程序一样启动后台线程并封送到“outlook线程”?Servy,我忘了您可以这样做。我看到一些其他的网络参考资料描述了如何做到这一点。这里有一个特别的:谢谢。我能够从这个线程中修改一些代码:
private void btn_syncContacts_Click(object sender, RibbonControlEventArgs e)
{
     Thread t = new Thread(SplashScreenProc);
     t.Start();

     //long running code
     this.SyncContacts();

     syncingSplash.Invoke(new Action(this.syncingSplash.Close), null);
}

private SyncingContactsForm syncingSplash = new SyncingContactsForm();

internal void SplashScreenProc(object param)
{
    this.syncingSplash.ShowDialog();
}