代码之家  ›  专栏  ›  技术社区  ›  Pondidum

从线程安全地引发事件

  •  1
  • Pondidum  · 技术社区  · 17 年前

    我确信我在某个地方读过如何使用委托事件(如此),但我找不到它。

    Public Class Form1
    
        Private WithEvents _to As New ThreadedOperation
    
        Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button.Click
            _to.start()
        End Sub
    
        Private Sub _to_SomthingHappend(ByVal result As Integer) Handles _to.SomthingHappend
            TextBox.Text = result.ToString //cross thread exception here
        End Sub
    
    End Class
    
    Public Class ThreadedOperation
    
        Public Event SomthingHappend(ByVal result As Integer)
        Private _thread As Threading.Thread
    
        Public Sub start()
            If _thread Is Nothing Then
                _thread = New Threading.Thread(AddressOf Work)
            End If
            _thread.Start()
        End Sub
    
        Private Sub Work()
            For i As Integer = 0 To 10
                RaiseEvent SomthingHappend(i)
                Threading.Thread.Sleep(500)
            Next
        End Sub
    
    End Class
    
    2 回复  |  直到 17 年前
        1
  •  2
  •   Hans Passant    17 年前

    您从控件派生了类。有点不寻常,但如果控件实际上托管在表单上,则可以使用Me.Invoke()封送调用。例如:

      Private Delegate Sub SomethingHappenedDelegate(ByVal result As Integer)
    
      Private Sub Work()
        For i As Integer = 0 To 10
          Me.Invoke(New SomethingHappenedDelegate(AddressOf SomethingHappenedThreadSafe), i)
          Threading.Thread.Sleep(500)
        Next
      End Sub
    
      Private Sub SomethingHappenedThreadSafe(ByVal result As Integer)
        RaiseEvent SomthingHappend(result)
      End Sub
    

      Private mHost As Form
    
      Public Sub New(ByVal host As Form)
        mHost = host
      End Sub
    

    并使用mHost.Invoke()。或开始唤醒()。

    本书的最后一个技巧是使用主启动窗体作为同步对象。这并不完全安全,但在99%的情况下都有效:

      Dim main As Form = Application.OpenForms(0)
      main.Invoke(New SomethingHappenedDelegate(AddressOf SomethingHappenedThreadSafe), i)
    

        2
  •  1
  •   Quibblesome    17 年前

    如果您想简化所有这些,有一个名为BackgroundWorker的类可以为您处理GUI线程封送。