2009-05-29 4 views
2

У меня есть форма окна на основном потоке и другой поток, который выполняет некоторые вычисления. Я хотел бы обновить строку состояния в моей форме из работы, выполняемой в другом потоке. Каков наилучший способ сделать это?Обновление строки прогресса из другой темы

До сих пор все, что я пробовал, просто заставляет вещи работать очень медленно. Я использую Visual Studio 2005.

+0

Вы должны быть более конкретными - что было медленным? как вы используете потоки? –

ответ

2

Убедитесь, что вы обновляете пользовательский интерфейс только из основного потока, иначе у вас будут проблемы. Вы можете переключить контекст потока, вызвав Invoke. Там хороший пост here.

1

Вы можете отправлять сообщения в основной поток и получать его, чтобы обновить индикатор выполнения, хотя вам необходимо проверить сообщения. Вы также можете сделать то же самое, что и функция опроса.

1

Вы можете использовать методы маршалинга, такие как Control.Invoke, для выполнения делегата в потоке пользовательского интерфейса, где элементы пользовательского интерфейса можно безопасно манипулировать, но этот подход не очень хорош. На самом деле, это ужасный подход, если все, что вы хотите сделать, это обновить простую информацию о ходе.

До сих пор лучший способ сделать это:

  • Попросите рабочий поток публиковать информацию о ходе общей переменной.
  • Проведите свой опрос по пользовательскому интерфейсу для него через System.Windows.Forms.Timers с интервалом, который хорошо работает для вас.

Вот как это могло бы выглядеть.

public class Example : Form 
{ 
    private volatile int percentComplete = 0; 

    private void StartThreadButton_Click(object sender, EventArgs args) 
    { 
    StatusBarUpdateTimer.Enabled = true; 
    new Thread(
    () => 
     { 
     for (int i = 1; i <= 100; i++) 
     { 
      DoSomeWork(); 
      percentComplete = i; 
     } 
     }).Start(); 
    } 

    private void StatusBarUpdateTimer_Tick(object sender, EventArgs args) 
    { 
    yourStatusBarPanel.Text = percentComplete.ToString() + "%"; 
    StatusBarUpdateTimer.Enabled = percentComplete < 100; 
    } 
} 

Это хорошо работает, потому что:

  • Пользовательский интерфейс поток получает диктовать, когда и как часто UI обновляется ... так оно и должно быть!
  • Рабочий поток не должен ждать ответа от потока пользовательского интерфейса, прежде чем он сможет продолжить, как в случае с Invoke.
  • Он разрушает плотную связь между пользовательским интерфейсом и рабочими потоками, которые накладывает Invoke.
  • Это более эффективно ... значительно.
  • Вы получаете большую пропускную способность как для пользовательского интерфейса, так и для рабочих потоков.
  • Невозможно насытить очередь сообщений пользовательского интерфейса, как это может быть в случае с BeginInvoke.
  • Вам не нужно подставлять код с помощью Invoke вызовов каждый раз, когда вам нужно обновить пользовательский интерфейс от рабочего потока.
Смежные вопросы