Я предлагаю вам сначала прочитать this для некоторого фона.
Смысл свойства InvokeRequired
состоит в том, чтобы определить, выполняете ли вы в данный момент поток, которому принадлежит указанный контроль или нет. InvokeRequired
равно False
, когда вы получаете его в потоке, который создал элемент управления, и True
в каждом другом потоке. Вообще говоря, все элементы управления создаются в одном потоке - в потоке, в котором было запущено приложение, - поэтому его часто называют потоком пользовательского интерфейса.
Если вы выполняете в потоке, создавшем элемент управления тогда безопасно получить доступ к другим членам этого контроля напрямую. Если вы находитесь в другом потоке, вам нужно вызвать вызов метода в потоке-владельце, иначе могут произойти плохие вещи. Методы Invoke
и BeginInvoke
выполняют вызов метода в потоке, создавшем элемент управления. Invoke
ожидает завершения вызова, в то время как BeginInvoke
немедленно возвращается, и код продолжает выполняться в текущем потоке, в то время как вызванный метод выполняется в потоке пользовательского интерфейса.
В вашем случае важной частью является следующее:
pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)
То есть доступ к свойству Image
PictureBox
, так что это должно быть сделано в потоке пользовательского интерфейса. Код проверяет свойство InvokeRequired
формы и, если это False
, это означает, что текущий код НЕ выполняется в потоке пользовательского интерфейса, поэтому небезопасен прямой доступ к этому свойству Image
. Метод BeginInvoke
выполнит указанное лямбда-выражение в потоке пользовательского интерфейса, что обеспечит безопасный доступ к этому свойству Image
в нем.
При вызове Invoke
или BeginInvoke
вы указываете метод Вы хотите выполнить, предоставив делегата. Делегат - это объект, который ссылается на метод. Делегаты для обычных именованных методов могут быть созданы с помощью оператора AddressOf
, что я и делаю в большинстве случаев в примерах, на которые я ссылался в начале этого ответа. Лямбда-выражение - это еще один способ создания делегата для анонимного метода. Этот код подобен написанию именованного метода, содержащего этот код:
imageMutex.WaitOne()
pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)
imageMutex.ReleaseMutex()
, а затем использование AddressOf
для создания делегата для этого метода. Это работает так, что методы Invoke
и BeginInvoke
работают со своими волхвами c в фоновом режиме для переключения контекста в поток пользовательского интерфейса, а затем выполняют метод, на который ссылается делегат в этом потоке.
Если вы не уверены, как делегаты работают или могут работать, вам может быть интересно узнать, что они - волхвы c за событиями. Событие - это в основном собрание делегатов. Рассмотрим Click
событие Button
. Вы пишете в своей форме метод, который хотите выполнить при нажатии Button
. Как Button
может выполнить этот метод? Регистрация обработчика события фактически создает делегата, который ссылается на этот метод, и добавляет его в коллекцию для этого события. Когда Button
вызывает событие, оно в основном перебирает коллекцию делегатов и вызывает каждого из них.