Вы можете использовать методы маршалинга, такие как 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
вызовов каждый раз, когда вам нужно обновить пользовательский интерфейс от рабочего потока.
Вы должны быть более конкретными - что было медленным? как вы используете потоки? –