2012-12-05 41 views
2

背景:进度对话框挂在Outlook中添加使用的DoEvents

我用一个简单的进度对话框中的Outlook插件,以显示进度,同时执行长时间操作。由于我无法在单独的线程中运行使用Outlook对象的代码,因此我无法实现更传统的后台工作进程。我的加载项一直工作正常,直到Outlook 2013在某些情况下我的进度对话框挂起。当我在VS调试器中运行加载项并导致挂起时,然后休息一下,它似乎停留在试图强制更新进度栏的DoEvents()行上。

我的问题:

有人能提出一个更好的系统,以显示与上述(长时间运行的代码必须在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); 
    } 
} 

这里有一个简单的进度对话框窗口中的代码:

public partial class DlgStatus : Form 
{ 
    private bool _cancelled; 

    public DlgStatus() 
    { 
     InitializeComponent(); 
    } 

    public int ProgressMax 
    { 
     set 
     { 
      progress.Maximum = value; 
      Application.DoEvents(); 
     } 
    } 

    public bool Cancelled 
    { 
     get { return _cancelled; } 
    } 

    public void SetProgress(string status, int val) 
    { 
     lblStatus.Text = status; 
     progress.Value = val; 
     Application.DoEvents(); //Seems to hang here 
    } 

    private void btnCancel_Click(object sender, EventArgs e) 
    { 
     _cancelled = true; 
     Application.DoEvents(); 
     this.Visible = false; 
    } 
} 
+0

为什么你不能像开始使用其他UI应用程序一样启动后台线程和编组到“outlook线程”? – Servy

+1

Servy,我忘了你可以做到这一点。我看到一些其他的Web引用描述了如何做到这一点。这里有一个特别的:[MSDN论坛链接](http://social.msdn.microsoft.com/Forums/da-DK/outlookdev/thread/5c5eeff3-408b-4430-bb27-9aea5a0503f9) – NetGeni59

回答

0

我能够通过执行以下操作来实现这一点。自定义窗体有一个进度条,其样式设置为“选取框”。

我从http://social.msdn.microsoft.com/Forums/en/vsto/thread/59993421-cbb5-4b7b-b6ff-8a28f74a1fe5得到的一般方法,但发现我不需要使用所有的自定义窗口句柄。

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建议不要在单独的线程上使用对象模型。

+0

谢谢。我能够从这个线程适应一些代码:http://stackoverflow.com/questions/4698080/spawn-a-new-thread-to-open-a-new-window-and-close-it-from-a - 不同的线程 – NetGeni59