Parâmetros e valores de retorno for Multithreaded Procedures (C# e Visual Basic)
Fornecer e retornar valores em um aplicativo com vários segmentos é complicado porque o construtor para o segmento de classe deve ser uma referência a um procedimento que não leva argumentos e não retorna nenhum valor.As seções a seguir mostram algumas maneiras simples de fornecer parâmetros e retornar valores de procedimentos em segmentos separados.
Fornecer Parâmetros para os Procedimentos Multi-threaded
A melhor maneira de fornecer parâmetros para um chamada de método com vários segmentos é para quebrar o método de destino em uma classe e definir campos para a classe que servirá como parâmetros para o novo segmento.A vantagem dessa abordagem é que você pode criar uma nova instância da classe, com seus próprios parâmetros, toda vez que quiser iniciar um novo segmento.Por exemplo, suponha que você tenha uma função que calcula a área de um triângulo, como no código a seguir:
Function CalcArea(ByVal Base As Double, ByVal Height As Double) As Double
CalcArea = 0.5 * Base * Height
End Function
double CalcArea(double Base, double Height)
{
return 0.5 * Base * Height;
}
Você pode escrever uma classe que quebra a função CalcArea e cria campos para armazenar parâmetros de entrada, da seguinte maneira:
Class AreaClass
Public Base As Double
Public Height As Double
Public Area As Double
Sub CalcArea()
Area = 0.5 * Base * Height
MessageBox.Show("The area is: " & Area.ToString)
End Sub
End Class
class AreaClass
{
public double Base;
public double Height;
public double Area;
public void CalcArea()
{
Area = 0.5 * Base * Height;
MessageBox.Show("The area is: " + Area.ToString());
}
}
Para usar AreaClass, você pode criar um objeto AreaClass e definir as propriedades Base e Height conforme mostrado no código o seguir:
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
protected void TestArea()
{
AreaClass AreaObject = new AreaClass();
System.Threading.Thread Thread =
new System.Threading.Thread(AreaObject.CalcArea);
AreaObject.Base = 30;
AreaObject.Height = 40;
Thread.Start();
}
Observe que o procedimento TestArea não verifica o valor do campo Area após chamar o método CalcArea.Como CalcArea é executado em um segmento separado, não se pode garantir que o campo Area será definido se você marcá-lo imediatamente após chamar Thread.Start.A próxima seção discute uma melhor forma para retornar valores de procedimentos com vários segmentos.
Retornar Valores dos Procedimentos Multi-threaded
Retornar valores de procedimentos executados em segmentos separados é complicado pelo fato de que os procedimentos não podem ser funções e não é possível usar argumentos ByRef.A maneira mais fácil de retornar valores é usar o componente BackgroundWorker para gerenciar seus segmentos e disparar um evento quando a tarefa estiver concluída e processar os resultados com um manipulador de eventos.
O exemplo a seguir retorna um valor ao disparar um evento a partir de um procedimento em execução em um segmento separado:
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)
MessageBox.Show("The area is: " & Area.ToString)
End Sub
class AreaClass2
{
public double Base;
public double Height;
public double CalcArea()
{
// Calculate the area of a triangle.
return 0.5 * Base * Height;
}
}
private System.ComponentModel.BackgroundWorker BackgroundWorker1
= new System.ComponentModel.BackgroundWorker();
private void TestArea2()
{
InitializeBackgroundWorker();
AreaClass2 AreaObject2 = new AreaClass2();
AreaObject2.Base = 30;
AreaObject2.Height = 40;
// Start the asynchronous operation.
BackgroundWorker1.RunWorkerAsync(AreaObject2);
}
private void InitializeBackgroundWorker()
{
// Attach event handlers to the BackgroundWorker object.
BackgroundWorker1.DoWork +=
new System.ComponentModel.DoWorkEventHandler(BackgroundWorker1_DoWork);
BackgroundWorker1.RunWorkerCompleted +=
new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted);
}
private void BackgroundWorker1_DoWork(
object sender,
System.ComponentModel.DoWorkEventArgs e)
{
AreaClass2 AreaObject2 = (AreaClass2)e.Argument;
// Return the value through the Result property.
e.Result = AreaObject2.CalcArea();
}
private void BackgroundWorker1_RunWorkerCompleted(
object sender,
System.ComponentModel.RunWorkerCompletedEventArgs e)
{
// Access the result through the Result property.
double Area = (double)e.Result;
MessageBox.Show("The area is: " + Area.ToString());
}
Você pode fornecer parâmetros e retornar valores para segmentos de pool de segmentos, usando a variável de objeto de estado ByVal opcional do método QueueUserWorkItem.Segmentos timer de segmento também oferecem suporte a um objeto de estado para essa finalidade.Para obter informações sobre o pool de segmento e timers de segmento, consulte Thread Pooling (C# e Visual Basic) e Timers (C# e Visual Basic) de segmento.
Consulte também
Tarefas
Passo a passo: Multithreading com o componente BackgroundWorker (C# e Visual Basic)
Referência
(C# e Visual Basic) de sincronização de segmento
Eventos (guia de programação do C#)
Representantes (guia de programação do C#)
Conceitos
Thread Pooling (C# e Visual Basic)
Aplicativos multithread (C# e Visual Basic)