3

我一直在分析一個基本上從服務器獲取數據並在GUI中顯示數據的WPF應用程序。WPF應用程序和緩慢的GUI響應問題

此代碼是不是我的,而應用程序從GUI響應速度慢有關的一個問題,我試圖找到這個問題的原因。

我想與大家分享我的想法,其中的問題可能是,我會想聽聽你想想,是否使任何意義或沒有。

從服務器獲取數據,應用程序使用7個線程(這是用這種方式,主要是因爲應用程序邏輯的實現,所以不要太在意,爲什麼7,而不只是一個... ),現在,每個線程通過調用一個方法來創建,稱爲CreateThreadForTask()

public void StartAllThreads() 
{ 
    this.CreateThreadForTask(Tasks.Task1); 
    this.CreateThreadForTask(Tasks.Task2); 
    this.CreateThreadForTask(Tasks.Task3); 
    this.CreateThreadForTask(Tasks.Task4); 
    this.CreateThreadForTask(Tasks.Task5); 
    this.CreateThreadForTask(Tasks.Task6); 
    this.CreateThreadForTask(Tasks.Task7); 
} 

public void CreateThreadForTask(Tasks task) 
{ 
    ... // this part of the code is not important 

    //! Initialize and start timer 
    timer = null; 
    timer = new DispatcherTimer(); 
    timer.Tick += new EventHandler(RunMainSyncForTask); 
    timer.Start(); 
} 

public void RunMainSyncForTask(object s, EventArgs e) 
{ 
    int sec = int.Parse(AppSettings.GetSetting("syncInterval")); 
    timer.Interval = new TimeSpan(0, 0, sec); 

    //threadCaller is a background worker 
    threadCaller = InitializeThread(); 
    threadCaller.DoWork += DoWorkEventHandler(StartSync); 
    threadCaller.RunWorkerAsync(); 
}

當我調試我注意到,所有線程都使用DispatcherTimer創建的代碼;我認爲應用程序正在創建7 DispatcherTimer's,並將定時器的Tick事件與RunMainSyncForTask()方法鏈接起來,該方法內部創建一個從服務器獲取數據並將該數據保存到本地數據庫的後臺工作器。

現在,這是從MSDN

的DispatcherTimer在每個調度循環的頂部重新評估被採取。

定時器不保證在發生時間間隔時精確執行,但它們保證在時間間隔發生之前不會執行。這是因爲DispatcherTimer操作像其他操作一樣放在Dispatcher隊列中。執行DispatcherTimer操作時,依賴於隊列中的其他作業及其優先級。

因此,基於此我相信應用程序每次定時器執行tick事件時都會發送線程垃圾信息,並且同時完成7次;由於DispatcherTimer特性,所有這些操作都被添加到Dispatcher隊列中,由於Dispatcher處於繁忙狀態,這會使GUI響應變慢。另外,應用程序的另一個問題是,運行時需要大約90-95%的CPU,我認爲如果我的假設是正確的,這也可能是導致此問題的原因。

所以,如果你能分享一些這方面的內心,我會感激。

謝謝。

+0

您是否試圖將數據傳回給GUI?嘗試辨別與主線程「同步」的原因。 – user7116 2011-03-17 22:31:02

+0

不,這些線程只將數據下載到本地數據庫,應用程序使用另一個線程每隔X秒更新一次GUI。 – Vic 2011-03-17 22:43:00

回答

1

由於您通過瘋狂的線程調用網絡設置了一種繁忙等待方式,因此您可以獲得90-95%的CPU。

如果您在使用本StartSync邏輯發佈狀態通知或獲取數據回GUI,你經歷了很多籃球的跳躍。如果你使用.Net 4.0,你應該切換到Task Parallel Library,讓框架爲你處理所有這些。它還支持優美取消等

如果你不希望使用TPL,我會建議,而不是傳遞Window小號Dispatcher(使用通常的嫌疑人:調用或BeginInvoke)或SynchronizationContext(異步地Post,與同步Send)到用於這些任務的單個任務,這些任務必須在GUI中完成。

+0

感謝您的回答,StartSync是將信息從服務器下載到本地數據庫的方法,此方法更新的GUI的唯一安全就是進度條,並且它使用Dispatcher.Invoke(),但GUI在它現在幾乎所有其他控制器上都很慢,因爲它是使用DispatcherTimer創建的,您是不是認爲這可能會將任務添加到Dispatcher隊列,從而導致GUI變慢?順便說一句,應用程序使用.Net 3.5 – Vic 2011-03-17 22:47:43