2010-05-11 61 views
1

如何在使用後臺線程時有效顯示文件的狀態?使用後臺線程時高效顯示文件狀態

舉例來說,可以說,我有一個100MB的文件:

當我通過一個線程(就像一個例子)做下面的代碼是在約1分鐘運行:

foreach(byte b in file.bytes) 
{ 
    WriteByte(b, xxx); 
} 

不過。 ..如果我想更新用戶,我必須使用委託從主線程更新用戶界面,下面的代碼需要 - 永遠 - 字面上我不知道多久,我仍然在等待,我創建了這個帖子,而不是甚至完成了30%。

int total = file.length; 
int current = 0; 
foreach(byte b in file.bytes) 
{ 
    current++; 
    UpdateCurrentFileStatus(current, total); 
    WriteByte(b, xxx); 
} 

public delegate void UpdateCurrentFileStatus(int cur, int total); 
public void UpdateCurrentFileStatus(int cur, int total) 
{ 
     // Check if invoke required, if so create instance of delegate 
     // the update the UI 

     if(this.InvokeRequired) 
     { 

     } 
     else 
     { 
      UpdateUI(...) 
     } 
} 

回答

1

我建議您根據經過的時間進行更新,以便無論文件大小或系統負載如何,都有可預測的更新時間間隔:

DateTime start = DateTime.Now; 
    foreach (byte b in file.bytes) 
    { 
     if ((DateTime.Now - start).TotalMilliseconds >= 200) 
     { 
      UpdateCurrentFileStatus(current, total); 
      start = DateTime.Now; 
     } 
    } 
+0

對於循環中的相對時間測量,使用'Stopwatch'或甚至'DateTime.UtcNow'好得多,它們比'DateTime.Now'快得多。 – 2010-05-12 00:48:54

+0

好點。我也沒有意識到,DateTime.UtcNow更快(沒有時區轉換)。學習回答別的東西總是一種享受! 你也可以使用System.Timer來更新UI,特別是如果工作在另一個線程上完成的話。 – 2010-05-12 15:56:09

+0

我喜歡這種方式迄今爲止最好,謝謝你的ebpower – schmoopy 2010-05-12 16:46:00

5

不要更新每個字節的UI。只更新每100k左右。

觀察:

int total = file.length; 
int current = 0; 
foreach(byte b in file.bytes) 
{ 
    current++; 
    if (current % 100000 == 0) 
    { 
     UpdateCurrentFileStatus(current, total); 
    } 
    WriteByte(b, xxx); 
} 
+0

非常奇怪,我正在想,在我回到這個頁面之前 - 我會給出一個鏡頭,看看...我的意思是即使每個1k字節... – schmoopy 2010-05-11 21:37:26

+0

也使用'Control.BeginInvoke'而不是'Invoke',所以工作線程不必等待UI線程。 – 2010-05-12 00:50:04

2

你過於頻繁地更新UI - 在一個100MB的文件的每一個字節會導致1次億UI更新(編組爲每個UI線程)。

將您的更新分成總文件大小的百分比,可能是10%甚至5%的增量。因此,如果文件大小爲100字節,請在10,20,30等處更新用戶界面。

相關問題