2012-07-25 26 views
1

我有一個模式對話框,只有當用戶單擊按鈕時彈出一個取消按鈕。 Aftre模式對話框彈出後,我想開始一個監視外部事件的漫長過程。如果事件發生,那麼對話框將自動關閉。用戶可以通過點擊取消按鈕取消監控過程。在模態對話框彈出後啓動長進程

我分配過程開始到顯示的事件

private void ProceedForm_Shown(object sender, System.EventArgs e) 
{ 
    controller.StartSwiping(); 
} 

的過程本身就是一個循環

public void StartSwiping() 
{   
    Status status; 
    do 
    { 
     status = CallForFeedback(); 
    } while (status == Status.Pending);   

    form.DialogResult = DialogResult.OK; 
    form.Close(); 
} 

過程開始罰款,但該對話框不會彈出,這樣用戶就可以不取消該過程。我也嘗試將啓動分配給Load事件,但沒有任何更改。 有什麼方法可以顯示對話框,然後啓動該過程?

謝謝

+4

對長時間運行的任務使用BackgroundWorker。 – LarsTech 2012-07-25 14:48:58

回答

4

你的問題是,你正在做的一切在UI線程。您需要將狀態監視循環放在單獨的線程中,以便UI線程可以保持響應。

有幾種方法可以做到這一點,但最簡單的地方開始是與BackgroundWorker class

1

使用Task做你LongRunning事件:

CancellationTokenSource _cancelationTokenSource = new CancellationTokenSource(); 
new Task(() => 
{ 
    //Do LongRunning task 
}, _cancelationTokenSource.Token, TaskCreationOptions.LongRunning).Start(); 

使用_cancelationTokenSource取消任務需要的時候。

1

我會將長時間運行的代碼移動到後臺線程上,因爲您正在阻止UI線程,這就是UI永不顯示的原因。

使用背景工人階級的控制器功能http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

當工作在後臺工作完成(即接收到事件),那麼你可以使用下面的機制回調到UI線程:

http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

注:文章說,你可以使用InvokeRequired檢查關閉,這將被認爲是不好的做法crossthreadexception,而不是處理它的正確方法,然後調用Windows窗體上的方法。

1

其他人建議使用BackgroundWorker或其他類型的後臺線程。雖然在許多情況下這是適當的,但可能有更好的解決方案。你不只是在做一些長時間運行的任務,你還在等待一些事情發生。而不是不斷地投票......不管它是什麼,你都應該使用事件。應該有一個事件在您完成時觸發,並且您應該訂閱該事件,以便在滿足正確條件時執行您需要執行的任何操作(即關閉對話框)。

+0

謝謝,這是絕對正確的,但我可以將事件處理程序分配給BackgroundWorker類,以在處理完成時執行某些操作。 – HamoriZ 2012-07-25 15:20:08

+0

@ZoltanHamori根據實現的不同,可能會在UI或非UI線程中觸發事件處理程序。很可能它將是一個非UI線程。如果它不是你想要的那個,你總是可以得到另一個。如果您處於非UI線程中,則可以編組到UI線程中,如果您處於UI線程中,則可以啓動一個新任務以在後臺運行。 – Servy 2012-07-25 15:24:18