![](/img/trans.png)
[英]Threads: Multiple BeginInvoke(Sub() …) -> programming style; Are tasks better?
[英]What does this BeginInvoke(Sub()) do?
我遇到以下代碼:
Public Sub fun_imageCallback(ByVal data As IntPtr, ByVal rows As Integer, ByVal cols As Integer, ByVal channels As Integer, ByVal timestamp As Long)
'Console.WriteLine(rows + " " + cols + " " + channels);
imageMutex.WaitOne()
If imageCamera IsNot Nothing Then
imageCamera.Dispose()
End If
imageCamera = New Bitmap(cols, rows, channels * cols, PixelFormat.Format8bppIndexed, data)
' The default palette has strange colours, not grayscale
Dim pal As ColorPalette = imageCamera.Palette
For i As Integer = 0 To 255
pal.Entries(i) = Color.FromArgb(i, i, i)
Next
imageCamera.Palette = pal
imageMutex.ReleaseMutex()
If Me.InvokeRequired Then
Me.BeginInvoke(
Sub()
imageMutex.WaitOne()
pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)
imageMutex.ReleaseMutex()
End Sub
)
End If
End Sub
我不明白以下 4 行的作用:
If Me.InvokeRequired Then
Me.BeginInvoke(
Sub()
imageMutex.WaitOne()
這要怎么讀?
謝謝!
我建議您先閱讀本文了解一些背景知識。
InvokeRequired
屬性的要點是確定您當前是否在擁有指定控件的線程上執行。 當您在創建控件的線程上獲取InvokeRequired
為False
時,在所有其他線程上獲取它為True
。 一般來說,所有控件都是在同一個線程上創建的——應用程序在其上啟動的線程——這就是為什么它通常被稱為 UI 線程。
如果您在創建控件的線程上執行,那么直接訪問該控件的其他成員是安全的。 如果您在不同的線程上,則需要在擁有線程上調用方法調用,否則可能會發生壞事。 Invoke
和BeginInvoke
方法在創建控件的線程上執行方法調用。 Invoke
等待調用完成,而BeginInvoke
立即返回,代碼繼續在當前線程上執行,而被調用的方法在 UI 線程上執行。
在您的情況下,重要的部分是:
pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)
這是訪問PictureBox
的Image
屬性,因此必須在 UI 線程上完成。 該代碼測試表單的InvokeRequired
屬性,如果為False
,則表示當前代碼未在 UI 線程上執行,因此直接訪問該Image
屬性是不安全的。 BeginInvoke
方法將在 UI 線程上執行指定的 Lambda 表達式,從而可以安全地訪問其中的Image
屬性。
調用Invoke
或BeginInvoke
時,您可以通過提供委托來指定要執行的方法。 委托是指方法的 object。 可以使用AddressOf
運算符創建常規命名方法的委托,這是我在本答案開頭鏈接的示例中的大多數情況下所做的。 Lambda 表達式是為匿名方法創建委托的另一種方法。 該代碼就像編寫包含此代碼的命名方法:
imageMutex.WaitOne()
pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)
imageMutex.ReleaseMutex()
然后使用AddressOf
為該方法創建一個委托。 它的工作方式是Invoke
和BeginInvoke
方法在后台發揮它們的魔力,將上下文切換到 UI 線程,然后它們在該線程上執行委托引用的方法。
如果您不確定代表如何工作或如何工作,您可能有興趣了解它們是事件背后的魔力。 事件基本上是代表的集合。 考慮Button
的Click
事件。 您在表單中編寫了一個方法,當單擊Button
時要執行該方法。 Button
如何執行該方法? 注冊事件處理程序實際上是創建一個引用該方法的委托並將其添加到該事件的集合中。 當Button
引發事件時,它基本上會遍歷委托集合並調用每個委托。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.