Понятие BeginInvoke и Invoke можно представить следующим образом.
- BeginInvoke означает: «Сделайте это и вернитесь до его завершения. Мне либо наплевать на возвращаемое значение, либо вы можете перезвонить мне по этому адресу в будущем».
- «Вызывать» означает: «Сделай это, и я сижу здесь и жду, пока оно завершится».
Теперь, как это относится к диспетчерам и фоновым потокам, это совсем другое дело. Как говорит Джастин, диспетчер обрабатывает очередь вещей, которые нужно делать каждый раз, когда поток пользовательского интерфейса становится бездействующим. Фоновый поток, который вызывает BeginInvoke для диспетчера, немедленно вернется, даже если диспетчер, возможно, не дошел до обработки. Если вместо этого использовался Invoke, фоновый поток блокировался до тех пор, пока поток пользовательского интерфейса не завершил обработку. Обратите внимание, что в Silverlight нет Invoke для Dispatcher, и в большинстве случаев вы, вероятно, не хотите, чтобы фоновый поток блокировался, пока поток пользовательского интерфейса обрабатывает работу.
И наоборот, Delegate.BeginInvoke использует рабочие потоки в пуле потоков. Когда вы в потоке пользовательского интерфейса (или в любом другом потоке), вы можете вызывать BeginInvoke и Invoke для делегата. BeginInvoke будет использовать рабочий поток для вызова делегата, используя ту же семантику, которую я описал выше. Однако Invoke не будет использовать другой поток. Это просто вызовет делегат синхронно в контексте вызывающего потока и вернет его после завершения.
Будьте осторожны при использовании синхронного выполнения между потоками, хотя это часто приводит к тупикам, если вы не очень осторожны.