簡體   English   中英

這個 BeginInvoke(Sub()) 做什么?

[英]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屬性的要點是確定您當前是否在擁有指定控件的線程上執行。 當您在創建控件的線程上獲取InvokeRequiredFalse時,在所有其他線程上獲取它為True 一般來說,所有控件都是在同一個線程上創建的——應用程序在其上啟動的線程——這就是為什么它通常被稱為 UI 線程。

如果您在創建控件的線程上執行,那么直接訪問該控件的其他成員是安全的。 如果您在不同的線程上,則需要在擁有線程上調用方法調用,否則可能會發生壞事。 InvokeBeginInvoke方法在創建控件的線程上執行方法調用。 Invoke等待調用完成,而BeginInvoke立即返回,代碼繼續在當前線程上執行,而被調用的方法在 UI 線程上執行。

在您的情況下,重要的部分是:

pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)

這是訪問PictureBoxImage屬性,因此必須在 UI 線程上完成。 該代碼測試表單的InvokeRequired屬性,如果為False ,則表示當前代碼未在 UI 線程上執行,因此直接訪問該Image屬性是不安全的。 BeginInvoke方法將在 UI 線程上執行指定的 Lambda 表達式,從而可以安全地訪問其中的Image屬性。

調用InvokeBeginInvoke時,您可以通過提供委托來指定要執行的方法。 委托是指方法的 object。 可以使用AddressOf運算符創建常規命名方法的委托,這是我在本答案開頭鏈接的示例中的大多數情況下所做的。 Lambda 表達式是為匿名方法創建委托的另一種方法。 該代碼就像編寫包含此代碼的命名方法:

imageMutex.WaitOne()
pbCamera.Image = DirectCast(imageCamera.Clone(), Bitmap)
imageMutex.ReleaseMutex()

然后使用AddressOf為該方法創建一個委托。 它的工作方式是InvokeBeginInvoke方法在后台發揮它們的魔力,將上下文切換到 UI 線程,然后它們在該線程上執行委托引用的方法。

如果您不確定代表如何工作或如何工作,您可能有興趣了解它們是事件背后的魔力。 事件基本上是代表的集合。 考慮ButtonClick事件。 您在表單中編寫了一個方法,當單擊Button時要執行該方法。 Button如何執行該方法? 注冊事件處理程序實際上是創建一個引用該方法的委托並將其添加到該事件的集合中。 Button引發事件時,它基本上會遍歷委托集合並調用每個委托。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM