Поделиться через


Параметры и возвращаемые значения для многопоточных процедур

Обновлен: Ноябрь 2007

При передаче параметров и возвращении значений в многопотоковое приложение, возникают дополнительные сложности, поскольку конструктору потока передается только ссылка на процедуру, которая не принимает аргументов и не возвращает значений. В следующих разделах показаны некоторые простые способы передачи параметров и возращения значений из процедур, выполняющихся в различных потоках.

Предоставление параметров для многопоточных процедур

Наилучшим способом передачи параметров при вызове многопотокового метода является заключение нужного метода в класс и определение полей для этого класса, которые будут использоваться в качестве параметров нового потока. Преимущество такого подхода заключается в возможности создания нового экземпляра класса со своими параметрами при каждом запуске нового потока. Рассмотрим, например, функцию, вычисляющую площадь треугольника, как показано в следующем примере кода:

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

Можно написать класс, который включает в себя функцию CalcArea и создает поля для хранения входных параметров, как показано ниже:

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

Чтобы использовать AreaClass, можно создать объект AreaClass и установить свойства Base и Height, как показано в следующем коде:

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

Обратите внимание, что процедура TestArea не будет проверять значение поля Area после вызова метода CalcArea. Поскольку CalcArea выполняется в отдельном потоке, не гарантируется, что поле Area будет задано, если проверить его сразу после вызова Thread.Start. В следующем разделе показан более удобный способ получения возвращаемых значений от многопотоковых процедур.

Получение возвращаемых значений от многопоточных процедур

Получение возвращаемых значений от процедур, выполняемых в отдельных потоках, осложняется тем, что процедуры не могут быть функциями и использовать аргументы ByRef. Наиболее простым способом является использование компонента BackgroundWorker для управления потоками и вызова события при завершении задачи и обработки результатов обработчиком событий.

Следующий пример показывает получение возвращаемого значения от процедуры, выполняющейся в отдельном потоке, путем создания события.

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

Передачу параметром и получение возвращаемых значений от потоков из группы потоков можно осуществлять при помощи дополнительной переменной статического объекта ByValметода QueueUserWorkItem. Потоки, запускаемые по таймеру потоков, также поддерживают статические объекты для данной цели. Информация о группировке потоков и потоковых таймеров содержится в разделе Группировка потоков в пул и Таймеры потоков.

См. также

Основные понятия

Состояния потоков

Группировка потоков в пул

Синхронизация потоков

События и обработчики событий

Многопоточные приложения

Использование многопоточности для форм и элементов управления

Делегаты и оператор AddressOf

Другие ресурсы

Многопоточность в компонентах