я иногда использую (в Load)
this.BeginInvoke((MethodInvoker) delegate {
// some code
});
или
this.BeginInvoke((MethodInvoker) this.SomeMethod);
(замените «this» на переменную формы, если вы обрабатываете событие в экземпляре, отличном от «this»).
Это помещает вызов в цикл windows-форм, поэтому он обрабатывается, когда форма обрабатывает очередь сообщений.
[обновляется по запросу]
Методы Control.Invoke / Control.BeginInvoke предназначены для использования с потоками и представляют собой механизм для переноса работы в поток пользовательского интерфейса. Обычно это используется рабочими потоками и т. Д. Control.Invoke выполняет синхронный вызов, а Control.BeginInvoke выполняет асинхронный вызов.
Обычно они используются как:
SomeCodeOrEventHandlerOnAWorkerThread()
{
// this code running on a worker thread...
string newText = ExpensiveMethod(); // perhaps a DB/web call
// now ask the UI thread to update itself
this.Invoke((MethodInvoker) delegate {
// this code runs on the UI thread!
this.Text = newText;
});
}
Это делается путем отправки сообщения в очередь сообщений Windows; поток пользовательского интерфейса (в какой-то момент) удаляет из очереди сообщение, обрабатывает делегата и сообщает работнику, что оно выполнено ... пока все хорошо; -p
OK; так что произойдет, если мы используем Control.Invoke / Control.BeginInvoke в потоке пользовательского интерфейса? Он справляется ... если вы вызываете Control.Invoke, достаточно разумно знать, что блокировка в очереди сообщений вызовет немедленную взаимоблокировку - поэтому, если вы уже находитесь в потоке пользовательского интерфейса, он просто сразу запускает код ... так что нам не помогает ...
Но Control.BeginInvoke работает по-другому: он всегда переносит работу в очередь, даже если мы уже находимся в потоке пользовательского интерфейса. Это действительно простой способ сказать «в одно мгновение», но без неудобств с таймерами и т. Д. (Которые все равно должны были бы делать то же самое в любом случае!).