2012-12-05 40 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