다음을 통해 공유


다중 스레드 프로시저의 매개 변수 및 반환 값(C# 및 Visual Basic)

다중 스레드 응용 프로그램에서 값을 지정하고 반환하는 것은 복잡합니다. 그 이유는 인수를 사용하지 않고 값을 반환하지도 않는 프로시저에 대한 참조가 스레드 클래스에 대한 생성자에 전달되어야 하기 때문입니다. 다음 단원에서는 별도의 스레드에 있는 프로시저에서 매개 변수를 지정하고 값을 반환하는 방법에 대해 간단하게 설명합니다.

다중 스레드 프로시저에 대한 매개 변수 지정

다중 스레드 메서드의 호출에 대해 매개 변수를 지정하는 가장 좋은 방법은 클래스의 대상 메서드를 래핑하고 새 스레드에 대해 매개 변수로 사용될 해당 클래스에 대한 필드를 정의하는 것입니다. 이 방법을 사용하면 새 스레드를 시작할 때마다 클래스의 새 인스턴스와 해당 매개 변수를 만들 수 있습니다. 예를 들어, 다음 코드와 같이 삼각형의 면적을 계산하는 함수가 있다고 가정합니다.

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;
}

이 경우 다음과 같이 CalcArea 함수를 래핑하고 입력 매개 변수를 저장하기 위한 필드를 만드는 클래스를 작성할 수 있습니다.

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());
    }
}

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
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();
}

이 때 TestArea 프로시저는 CalcArea 메서드를 호출한 후 Area 필드의 값을 확인하지 않습니다. CalcArea는 별도의 스레드에서 실행되므로 Thread.Start를 호출한 직후에 Area 필드를 확인하면 Area 필드가 설정되어 있지 않을 수도 있습니다. 다음 단원에서는 다중 스레드 프로시저에서 값을 반환할 수 있는 좀 더 유용한 방법에 대해 설명합니다.

다중 스레드 프로시저에서 값 반환

프로시저는 함수가 될 수 없으며 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)
    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());
}

QueueUserWorkItem 메서드의 선택적 상태 개체 변수인 ByVal을 사용하면 스레드 풀 스레드에 매개 변수와 반환 값을 제공할 수 있습니다. 스레드 타이머 스레드에서도 이러한 용도의 상태 개체를 지원합니다. 스레드 풀링 및 스레드 타이머에 대한 자세한 내용은 스레드 풀링(C# 및 Visual Basic)스레드 타이머(C# 및 Visual Basic)를 참조하십시오.

참고 항목

작업

연습: BackgroundWorker 구성 요소를 사용한 다중 스레딩(C# 및 Visual Basic)

참조

스레드 동기화(C# 및 Visual Basic)

이벤트(C# 프로그래밍 가이드)

대리자(C# 프로그래밍 가이드)

개념

스레드 풀링(C# 및 Visual Basic)

다중 스레드 응용 프로그램(C# 및 Visual Basic)

기타 리소스

이벤트(Visual Basic)

대리자(Visual Basic)

구성 요소에서 다중 스레딩