c# - C# 正在等待長時間的進程並仍在更新用戶界面

  显示原文与译文双语对照的内容
148 1

我一直在嘗試創建一個在不阻塞用戶界麵線程的情況下寫入資料庫的任務。我所擁有的最大問題是等待過程完成而不會發生阻塞。

我一直在嘗試避免使用 DoEvents ( 儘管現在通過這個程序使用得非常頻繁,但是我想在前進時使用它。) 。

我試圖創建運行在 2nd 線程上的進程並等待它完成,並使用 BackgroundWorker

這個問題並不是讓代碼運行在一個不同的線程中,而是試圖找到等待它完成的方法。

基本上,現在我執行以下操作:

  • 連接到資料庫
  • 創建一個後台工作人員( 或者線程) 來寫入資料庫( 可以能最終會使用 BackgroundWorker,這樣可以以使用 ReportProgress ) 。
  • 啟動線程或者 BackgroundWorker
  • 使用while循環wait等待線程/BackgroundWorker 完成。對於線程,我等待 IsAlive 成為 false,對於 BackgroundWorker,我切換一個布爾變數。
  • 我讓用戶知道這個過程已經完成了。

問題在 #4. 中

在不包含代碼的情況下執行循環,或者 Thread.Sleep(0) 離開了UI阻塞( Thread.Sleep(0) 使得程序佔用程序資源的100%個)

所以我這樣做:

while (!thread.IsAlive)
 Thread.Sleep(1);

-or -

while (bProcessIsRunning)
 Thread.Sleep(1);

它阻止了用戶界面。

如果我在那裡調用 Application.DoEvents(),則更新( 雖然是可以點擊的,因此我必須在這個進程運行時禁用整個表單) 。

如果同步運行流程,我仍然需要創建一些用於更新( 在我看來一個 DoEvents 電話)的方法,因這裡它不會被鎖定。

我做錯什麼了?

时间:原作者:0个回答

80 3

C# 使用事件模型--調度執行工作的進程,然後使進程在完成或者使用一個線程事件時激發。當進程在"背景"釋放控制項中運行時,從代碼返回到系統。

原作者:
145 2

首先,你為什麼希望避免 DoEvents()

其次,你使用的是衝突的術語。

等待==阻塞

要想阻止用戶界麵線程,請按 ,但要等待任務完成,請等待。這些是互斥的狀態。如果你正在等待某事完成,你會阻止你的線程。

如果你想讓用戶界面真正可用,可用的( 未被阻止),那麼你不需要等待,因為你的任務完成了。僅 register 完成時激發的事件處理程序。例如使用BackgroundWorker處理 RunWorkerCompleted 事件。對於任務,可以使用continuation將回調分派給主線程。

但是似乎你只是想更新 UI,而不使用。通常只有在希望進度條或者它的他UI動畫繼續移動時才有意義。這種情況下,我將打開一個模式對話框,啟動任務,然後等待它,是的,調用 DoEvents() 。

 var dialog = new MessageBoxFormWithNoButtons("Please wait while I flip the jiggamawizzer");
 dialog.Shown += (_, __) =>
 {
 var task = Task.Factory.StartNew(() => WriteToDatabase(), TaskCreationOptions.LongRunning);
 while (!task.Wait(50))//wait for 50 milliseconds (make shorter for smoother UI animation)
 Application.DoEvents();//allow UI to look alive
 dialog.Close();
 }
 dialog.ShowDialog();

模態對話框阻止用戶執行任何操作,但是任何動畫仍然由 DoEvents() 調用 20倍。

( 你可能希望為不同的任務完成狀態添加特殊處理,但這是跑題了。)

原作者:
...