การสื่อสารข้ามเธรดและการอัพเดตภาคสนามใน VB.NET

ฉันประสบปัญหาในการทำให้การสื่อสารข้ามเธรด/การอัปเดตฟิลด์ทำงานอย่างถูกต้องในโปรแกรม VB.NET 2010 ของฉัน ฉันกำลังพยายามอัปเดตฟิลด์ในแบบฟอร์มหลักของฉันเมื่อใดก็ตามที่เธรดที่ฉันเริ่มส่งเหตุการณ์ นี่คือโค้ดเวอร์ชันที่เรียบง่ายของฉัน:

แบบฟอร์มหลักของฉัน:

Public Class Main
    ' stuff

    ' Eventually, startProcessing gets called:
    Private Sub startProcessing()
        Dim processingClass = New MyProcessingClass("whatever")
        AddHandler processingClass.processStatusUpdate, AddressOf handleProcessStatusUpdate
        Dim processingThread = New Thread(AddressOf processingClass.process)
        processingThread.Start()
    End Sub

    Private Sub handleProcessStatusUpdate(statusUpdate As String)
        txtMainFormTextBox.Text = statusUpdate ' InvalidOperationException
        ' "Cross-threaded operation not valid: Control 'txtMainFormTextBox' accessed from a thread other than the thread it was created on"
    End Sub
End Class

ชั้นเรียนที่จัดกิจกรรม:

Public Class MyProcessingClass
    Private whatever As String    

    Public Event processStatusUpdate(status As String)

    Public Sub New(inWhatever As String)
        whatever = inWhatever
    End Sub

    Public Sub process()
        ' do some stuff
        RaiseEvent processStatusUpdate(whatever)
    End Sub
End Class

อย่างที่คุณเห็น ตัวจัดการในคลาสหลักของฉันไม่สามารถเข้าถึงกล่องข้อความที่ฉันต้องการได้เนื่องจากมันถูกทริกเกอร์โดยเธรดอื่น (ฉันคิดว่า) ฉันได้ลองใช้วิธีอื่นๆ หลายวิธีเพื่อให้สิ่งนี้ได้ผล รวมถึง:

  1. ย้ายตัวจัดการเหตุการณ์ไปที่ MyProcessingClass และส่ง txtMainFormTextBox โดยการอ้างอิง (ByRef) ไปยังคลาส
  2. การให้เธรดจริงเริ่มต้นภายใน MyProcessingClass แทนที่จะเป็น Main

สิ่งเหล่านี้ไม่ได้ผล เห็นได้ชัดว่ามีแนวคิดที่ฉันขาดหายไปที่นี่ วิธีที่ดีที่สุดในการทำสิ่งนี้ให้สำเร็จคืออะไร? ขอบคุณ!


person Mike Cialowicz    schedule 24.01.2011    source แหล่งที่มา


คำตอบ (1)


คุณต้องอัปเดตกล่องข้อความบนเธรด UI โดยโทร BeginInvoke


คุณควรใช้ BackgroundWorker คอมโพเนนต์ ซึ่งทำหน้าที่ทั้งหมด สิ่งนี้สำหรับคุณ
เพียงจัดการเหตุการณ์ DoWork และ ProgressChanged

person SLaks    schedule 24.01.2011
comment
ปัญหาของ BeginInvoke คือฉันไม่สามารถผ่าน aguments เมื่อใช้งาน ดังนั้นฉันจึงใช้ statusString ไม่ได้ ฉันจะดู BackgroundWorker... - person Mike Cialowicz; 24.01.2011
comment
@Mike: คุณสามารถส่งผ่านข้อโต้แย้งไปที่ BeginInvoke เพียงใช้ Action(Of String) อย่างไรก็ตาม คุณควรใช้ BackgroundWorker แทน - person SLaks; 24.01.2011