2010-05-11 1 views
1

Как я могу эффективно отображать состояние файла при использовании фонового потока?Эффективно отображать состояние файла при использовании фонового потока

Например, предположим, что у меня есть 100MB файл:

когда я делаю код ниже с помощью резьбы (только в качестве примера), в котором выполняется примерно 1 мин:

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

Но. .. если я хочу обновить пользователя, я должен использовать делегат для обновления пользовательского интерфейса из основного потока, код ниже берет - FOREVER - буквально я не знаю, как долго я все еще жду, я создал этот пост, а его нет даже 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

Для измерения относительного времени в цикле гораздо лучше использовать 'Секундомер' или даже' DateTime.UtcNow', которые намного быстрее, чем 'DateTime.Now'. –

+0

Хорошая точка. Я также не понимал, что DateTime.UtcNow работает быстрее (без изменения часового пояса). Это всегда удовольствие, чтобы узнать что-то от ответа на что-то еще! Вы также можете использовать System.Timer для обновления пользовательского интерфейса, особенно если работа выполняется в другом потоке. –

+0

Мне нравится этот подход, лучший пока, спасибо ebpower – schmoopy

5

Не обновляйте пользовательский интерфейс на каждом байте. обновите его только на каждые 100 тыс. или около того.

Наблюдайте:

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

+0

Также используйте 'Control.BeginInvoke' вместо 'Invoke', поэтому рабочий поток не должен ждать потока пользовательского интерфейса. –

2

Вы обновления UI слишком часто - каждый байт в файле 100MB собирается привести 100 миллионов обновлений пользовательского интерфейса (сортировочных в потоке пользовательского интерфейса для каждого).

Переведите обновления в процентах от общего размера файла, возможно, 10% или даже 5%. Поэтому, если размер файла равен 100 байт, обновите пользовательский интерфейс на 10, 20, 30 и т. Д.