Как использовать BeginInvoke С#
Не могли бы вы объяснить это мне, пожалуйста:
someformobj.BeginInvoke((Action)(() =>
{
someformobj.listBox1.SelectedIndex = 0;
}));
Не могли бы вы рассказать мне, как я могу использовать begininvoke
точно?
Что такое тип Action
?
Почему есть пустые скобки ()
?
И что это значит =>
?
Ответы
Ответ 1
Action
- это тип делегата, предоставляемый платформой .NET. Action
указывает на метод без параметров и не возвращает значение.
() =>
- синтаксис лямбда-выражения. Лямбда-выражения не относятся к типу Delegate
. Invoke требует Delegate
, поэтому Action
можно использовать для обертки лямбда-выражения и обеспечения ожидаемого Type
до Invoke()
Invoke
вызывает упомянутый Action
для выполнения в потоке, который создал дескриптор окна управления. Часто требуется изменение потоков, чтобы избежать Exceptions
. Например, если вы пытаетесь установить свойство Rtf
на RichTextBox
, когда требуется Invoke, без первого вызова Invoke, будет выбрано исключение Cross-thread operation not valid
. Перед вызовом Invoke откройте Control.InvokeRequired
.
BeginInvoke
- это асинхронная версия Invoke
. Асинхронный означает, что поток не будет блокировать вызывающего абонента в отличие от синхронного вызова, который блокируется.
Ответ 2
Я думаю, ваш код относится к Windows Forms.
Вы вызываете BeginInvoke
, если вам нужно что-то выполнить асинхронно в потоке пользовательского интерфейса: изменить свойства управления в большинстве случаев.
Грубо говоря, это достигается передачей делегата какой-либо процедуре, которая периодически выполняется. (обработка цикла сообщений и все такое)
Если BeginInvoke
вызывается для типа Delegate
, делегат просто вызывается асинхронно.
(Invoke
для версии синхронизации.)
Если вам нужен более универсальный код, который отлично работает для WPF и WinForms, вы можете рассмотреть параллельную библиотеку задач и запустить Task
с помощью context. (TaskScheduler.FromCurrentSynchronizationContext()
)
И добавить немного к уже сказанным другими:
Lambdas можно рассматривать как анонимные методы или expressions.
И поэтому вы не можете просто использовать var
с lambdas: компилятор нуждается в подсказке.
UPDATE:
для этого требуется .Net v4.0 и выше
// This line must be called in UI thread to get correct scheduler
var scheduler = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext();
// this can be called anywhere
var task = new System.Threading.Tasks.Task( () => someformobj.listBox1.SelectedIndex = 0);
// also can be called anywhere. Task will be scheduled for execution.
// And *IF I'm not mistaken* can be (or even will be executed synchronously)
// if this call is made from GUI thread. (to be checked)
task.Start(scheduler);
Если вы запустили задачу из другого потока и должны дождаться своего завершения, task.Wait()
будет блокировать вызов потока до конца задачи.
Подробнее о задачах здесь.