Вы должны ознакомиться с методами Invoke (...) и BeginInvoke (...) и определить, какая семантика необходима для этого межпоточного обновления. Хотите запустить и забыть, а не ждать, пока насос сообщений вернется к вашему текстовому обновлению? Используйте BeginInvoke(...)
. Вы хотите, чтобы поток блокировался до обновления UI? Используйте Invoke(...)
.
Кроме того, имейте в виду, что если форма потенциально может быть удалена или еще не была показана, перед вызовом Invoke(...)
или BeginInvoke(...)
необходимо проверить не только флаг InvokeRequired
в форме. Если есть вероятность этого случая, ваша логика должна выглядеть примерно так:
public void DoSomeUpdate(string text)
{
if(this.IsDisposed || (!this.IsHandleCreated))
{
// error condition; run away!
return;
}
if(this.InvokeRequired)
{
// BeginInvoke or Invoke here, based on the semantics you need
return;
}
this.UpdateSomeLabel(text);
}
Прокомментируйте, пожалуйста, если что-то здесь неясно.
Обновление
Был некоторый комментарий относительно проверки того, была ли создана ручка управления или была ли она удалена.
Что касается первого случая (IsHandleCreated
), это, безусловно, то, что вы можете предположить заранее во многих случаях; Однако не во всех случаях. Если вы не создаете динамически элементы управления, и ваши фоновые потоки запускаются через поток пользовательского интерфейса, вы, вероятно, в безопасности. Однако ...
Если есть какая-либо подсказка о том, что задание фонового потока может быть достаточно продолжительным, чтобы вы могли щелкнуть «X» в форме и закрыть ее (тем самым утилизировав ее), тогда вы получите приятное исключение. если вы не проверите IsDisposed
перед звонком Invoke(...)
или BeginInvoke(...)
. Это похоже на (в C) проверку на malloc(...)
, возвращающую что-то ненулевое. Это случается Как бы утомительно это ни было, автор приложения обязан заботиться об этих случаях потенциальной ошибки. Это добавляет осложнений; однако это важно, особенно если вы не хотите, чтобы ваше приложение зависало. Неправильный учет учетных записей IsDisposed
и IsHandleCreated
при вызове Invoke(...)
или BeginInvoke(...)
подвергает вас возможности сбоя приложения. Вы можете избежать этого сбоя с помощью нескольких дополнительных строк кода.