2011-04-02 71 views
1

我正試圖實現此處顯示的MSDN異步模式示例:http://msdn.microsoft.com/en-us/library/8wy069k1%28v=VS.90%29.aspx。在該示例中,ProgressChanged事件的觸發頻率等於UI在處理事件時掛起。請注意,我改變了:使用C#異步模式更新UI時出現問題

int testNumber = rand.Next(200000); 

int testNumber = 20000000; 

startAsyncButton_Click更好地測試了這種情況。

進度欄確實按預期進行更新,但所有其他UI事件都已掛起。如果我在BuildPrimeNumberList方法改變

// Yield the rest of this time slice. 
Thread.Sleep(0); 

// Yield the rest of this time slice. 
Thread.Sleep(1); 

,該UI開始響應位這違背使用線程的性能的目的。

任何人都可以推薦一種方法,有效地讓用戶界面在這個例子中保持響應嗎?

謝謝

+0

多線程的這種用法是不是真正的性能,它是關於無鎖定UI進行長時間運行的操作。在性能可能非常關鍵(非常罕見)的現實世界中,您可以更簡單地更新UI。 – AndrewS 2011-04-02 03:40:06

回答

1

這是MSDN上一個令人誤解的例子。對於在後臺線程上執行工作並保持活動狀態並通知後臺進度的場景,請使用BackgroundWorker類。 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

+0

因此,對於我的教育,它是如何誤導。此外,在什麼情況下你會使用文章中描述的模式與背景工作者類? – dtrain 2011-04-02 03:45:30

+1

我會使用基於事件的模型或IAsyncResult模型(第三個選項)在後臺執行單個操作,如調用Web服務。對於長時間運行或多操作任務,backgroundworker是專門爲此目的而創建的。 – 2011-04-02 03:55:22

0

在這種情況下,或者報告進度妨礙了實際工作的任何其他情況下,關鍵是報告進度不太頻繁,或者至少限制嘗試的UI更新量。

此示例已經有一個機制:progressInterval值確定進度事件導致UI更新的頻率。我敢打賭,這裏的問題是每100次報告的進度仍然過多。

而不是報告每X次重複(這將不隨着處理器功率的增加而擴展),將DateTime存儲在每個UI更新上可能會更好,然後忽略再次更新UI,直到至少250- 500ms已經過去了。

+0

更改Thread.Sleep(1)完成。它可以防止事件頻繁發生。更改時間間隔仍會導致UI掛起 – dtrain 2011-04-02 03:52:40

1

注意從例如

// This event handler updates the ListView control when the 
    // PrimeNumberCalculator raises the ProgressChanged event. 
    // 
    // On fast computers, the PrimeNumberCalculator can raise many 
    // successive ProgressChanged events, so the user interface 
    // may be flooded with messages. To prevent the user interface 
    // from hanging, progress is only reported at intervals. 
    private void primeNumberCalculator1_ProgressChanged(
     ProgressChangedEventArgs e) 
    { 

    } 

的意見,我覺得你的電腦是如此之快是生產過多的事件。

嘗試改變報告間隔:

private int progressInterval = 100; 

private int progressInterval = 1000; 
+0

將BuildPrimeNumberList中的Thread.Sleep更改爲Thread.Sleep(1)可以通過防止事件被頻繁觸發來完成。改變時間間隔不會。用戶界面仍然掛起 – dtrain 2011-04-02 03:55:01

+0

嘗試使它更大,10000。如果這不起作用;在primeNumberCalculator1_ProgressChanged嘗試放回去;作爲第一行,應該繞過UI更新,看看它是否仍然掛起程序。如果是這樣,您可能需要扼制鏈上的事件(例如asyncOp.Post(this.onProgressReportDelegate,e);) – djeeg 2011-04-02 04:14:25