Freigeben über


Parameter und Rückgabewerte für Multithreadprozeduren

Aktualisiert: November 2007

Die Bereitstellung und Rückgabe von Werten ist in einer Multithreadanwendung relativ kompliziert, da dem Konstruktor für die Threadklasse ein Verweis auf eine Prozedur übergeben werden muss, die keine Argumente akzeptiert und keinen Wert zurückgibt. In den folgenden Abschnitten wird beschrieben, wie auf einfache Weise Parameter bereitgestellt und Werte aus Prozeduren in separaten Threads zurückgegeben werden können.

Bereitstellen von Parametern für Multithread­prozeduren

Die einfachste Methode, Parameter für den Aufruf einer Multithreadmethode bereit­zustellen, besteht darin, die Zielmethode in eine Klasse einzubinden und für diese Klasse Felder zu definieren, die als Parameter für den neuen Thread verwendet werden. Dieser Ansatz hat den Vorteil, dass Sie jedes Mal, wenn ein neuer Thread gestartet werden soll, eine neue Instanz der Klasse mit eigenen Parametern erstellen können. Angenommen, Sie verwenden eine Funktion, die die Fläche eines Dreiecks berechnet, wie in folgendem Codebeispiel:

Function CalcArea(ByVal Base As Double, ByVal Height As Double) As Double
    CalcArea = 0.5 * Base * Height
End Function

Sie können wie folgt eine Klasse programmieren, die die CalcArea-Funktion einbindet und Felder zum Speichern von Eingabeparametern erstellt:

Class AreaClass
    Public Base As Double
    Public Height As Double
    Public Area As Double
    Sub CalcArea()
        Area = 0.5 * Base * Height
        MsgBox("The area is: " & Area)
    End Sub
End Class

Wenn Sie AreaClass verwenden möchten, können Sie ein AreaClass-Objekt erstellen und die Eigenschaften Base und Height festlegen, wie in folgendem Codebeispiel gezeigt:

Protected Sub TestArea()
    Dim AreaObject As New AreaClass
    Dim Thread As New System.Threading.Thread _
                     (AddressOf AreaObject.CalcArea)
    AreaObject.Base = 30
    AreaObject.Height = 40
    Thread.Start()
End Sub

Beachten Sie, dass die TestArea-Prozedur nach dem Aufrufen der CalcArea-Methode nicht den Wert des Area-Feldes überprüft. Da CalcArea in einem separaten Thread ausgeführt wird, ist es nicht sicher, dass das Area-Feld festgelegt ist, wenn es unmittelbar nach dem Aufrufen von Thread.Start überprüft wird. Im nächsten Abschnitt wird eine bessere Methode für die Rückgabe von Werten aus Multithreadprozeduren beschrieben.

Rückgabe von Werten aus Multithreadprozeduren

Die Rückgabe von Werten aus Prozeduren, die in separaten Threads ausgeführt werden, gestaltet sich etwas kompliziert. Grund hierfür ist, dass Prozeduren keine Funktionen sein können und keine ByRef-Argumente verwenden dürfen. Die einfachste Möglichkeit zum Zurückgeben von Werten ist die Verwendung der BackgroundWorker-Komponente, um die Threads zu verwalten und nach Abschluss der Aufgabe ein Ereignis auszulösen, und die Ergebnisse mit einem Ereignishandler zu verarbeiten.

Im folgenden Beispiel wird ein Wert zurückgegeben, indem ein Ereignis aus einer Prozedur ausgelöst wird, die in einem separaten Thread ausgeführt wird:

Private Class AreaClass2
    Public Base As Double
    Public Height As Double
    Function CalcArea() As Double
        ' Calculate the area of a triangle.
        Return 0.5 * Base * Height
    End Function
End Class

Private WithEvents BackgroundWorker1 As New System.ComponentModel.BackgroundWorker

Private Sub TestArea2()
    Dim AreaObject2 As New AreaClass2
    AreaObject2.Base = 30
    AreaObject2.Height = 40

    ' Start the asynchronous operation.
    BackgroundWorker1.RunWorkerAsync(AreaObject2)
End Sub

' This method runs on the background thread when it starts.
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) _
    Handles BackgroundWorker1.DoWork

    Dim AreaObject2 As AreaClass2 = CType(e.Argument, AreaClass2)
    ' Return the value through the Result property.
    e.Result = AreaObject2.CalcArea()
End Sub

' This method runs on the main thread when the background thread finishes.
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, _
    ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
    Handles BackgroundWorker1.RunWorkerCompleted

    ' Access the result through the Result property.
    Dim Area As Double = CDbl(e.Result)
    MsgBox("The area is: " & Area)
End Sub

Sie können Parameter und Rückgabewerte für Threadpool-Threads bereitstellen, indem Sie die optionale ByVal-Zustandsobjektvariable der QueueUserWorkItem-Methode verwenden. Threadzeitgeber-Threads unterstützen ebenfalls ein Zustandsobjekt für diesen Zweck. Informationen über Threadpooling und Threadzeitgeber finden Sie unter Pooling von Threads und unter Threadzeitgeber

Siehe auch

Konzepte

Threadstatuswerte

Pooling von Threads

Threadsynchronisierung

Ereignisse und Ereignishandler

Multithreadanwendungen

Multithreading bei Formularen und Steuerelementen

Delegaten und der AddressOf-Operator

Weitere Ressourcen

Multithreading in Komponenten