다음을 통해 공유


비동기

Asynchronous 샘플은 클라이언트가 서비스 작업에 비동기적으로 액세스할 수 있는 방법과 서비스가 해당 작업을 비동기적으로 구현할 수 있는 방법을 보여 줍니다. 이 샘플은 계산기 서비스를 구현하는 Getting Started 샘플을 기반으로 합니다. 동기 또는 비동기 호출을 사용하는 것은 로컬 결정이며 연결을 통해 보내는 메시지에 영향을 주지 않습니다. 서비스에서 일부 동기 작업을 구현하지만 클라이언트는 서비스 작업에 비동기적으로 액세스할 수 있습니다. 클라이언트가 서비스를 동기적으로 호출하더라고 서비스는 일부 작업을 비동기적으로 구현할 수 있습니다.

참고

이 샘플을 빌드하고 실행하려면 .NET Framework 버전 3.5를 설치해야 하고, 프로젝트 및 솔루션 파일을 열려면 Visual Studio 2008이 필요합니다.

참고

이 샘플의 설치 절차 및 빌드 지침은 이 항목의 끝부분에 나와 있습니다.

이 샘플에서 클라이언트는 콘솔 응용 프로그램(.exe)이고 서비스는 콘솔 응용 프로그램(.exe)에서 자체 호스팅됩니다.

서비스는 ICalculator 인터페이스를 구현합니다. 클라이언트는 이 인터페이스에서 비동기적으로 작업을 호출할 수 있으며 이는 Add와 같은 작업이 이제 BeginAddEndAdd를 가진다는 것을 의미합니다.

참고

비동기 패턴에 대한 자세한 내용은 .NET Framework 설명서를 참조하십시오.

클라이언트는 이러한 비동기 작업을 지원하는 코드를 생성했습니다. 다음과 같이 /a (async) 명령 옵션과 함께 Service Metadata Utility Tool (Svcutil.exe) 도구를 실행하여 클라이언트를 만들었습니다.

svcutil /n:http://Microsoft.ServiceModel.Samples,Microsoft.ServiceModel.Samples https://localhost:8000/servicemodelsamples/service/mex /a /tcv:Version35

다음 코드와 비슷하게 Add 작업에 대해 서비스 계약의 클라이언트 비동기 버전이 표시됩니다.

[System.ServiceModel.ServiceContractAttribute(Namespace=
                   "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [System.ServiceModel.OperationContractAttribute(
       AsyncPattern=true)]
    System.IAsyncResult BeginAdd(double n1, double n2, 
                   System.AsyncCallback callback, object asyncState);
    double EndAdd(System.IAsyncResult result);
    
    ...
}

/tcv:Version35 옵션이 /async 옵션과 함께 지정된 경우 생성된 클라이언트 형식은 서비스를 호출하기 위한 이벤트 기반 비동기 패턴을 구현합니다. 자세한 내용은 이벤트 기반 비동기 패턴 개요를 참조하십시오. 다음 샘플 코드와 같이 서비스 작업에 비동기적으로 액세스하기 위해 응용 프로그램은 클라이언트에서 [Operation]Completed 이벤트에 이벤트 처리기를 추가한 다음 [Operation]Async 메서드(예: AddAsync)를 호출합니다.

// Create a client.
CalculatorClient client = new CalculatorClient();

// BeginAdd.
double value1 = 100.00D;
double value2 = 15.99D;

client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
client.AddAsync(value1, value2);

샘플에서 클라이언트는 두 개의 작업인 AddSubtract를 비동기적으로 시작합니다.

콜백 함수가 실행되면 클라이언트는 [Operation]CompletedEventArgs 입력 매개 변수의 Result 속성에 액세스하여 결과를 검색합니다.

static void AddCallback(object sender, AddCompletedEventArgs e)
{
 Console.WriteLine("Add Result: {0}", e.Result);
}

모든 비동기 동작은 클라이언트에 대해 로컬이며 메시지가 클라이언트에서 보내지거나 서비스에 의해 처리되는 방법과 관련이 없습니다. UI(사용자 인터페이스) 응용 프로그램에서 이 패턴을 사용하는 일반적인 이유는 화면 업데이트를 위해 UI 스레드를 사용 가능한 상태로 유지할 수 있기 때문입니다. 또한 서비스가 클라이언트로 작동하는 중이고 다른 서비스에 대한 호출에서 메시지 처리 스레드를 확보하려는 경우 이 패턴을 적용할 수 있습니다. 다음 단원에서는 서비스 작업을 비동기적으로 만드는 방법을 보여 줍니다.

다음 코드와 같이 서비스는 ICalculator 인터페이스를 구현합니다.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);
    
    [OperationContract]
    double Subtract(double n1, double n2);
    
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginMultiply(double n1, double n2,
        AsyncCallback callback, object state);
    double EndMultiply(IAsyncResult ar);

    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginDivide(double n1, double n2, 
        AsyncCallback callback, object state);
    double EndDivide(IAsyncResult ar); 
}

계약의 처음 두 개 작업은 WCF(Windows Communication Foundation) 런타임에 의해 비동기적으로 호출됩니다. 마지막 두 개의 작업 쌍은 서비스를 비동기적으로 호출하는 데 사용됩니다. 이 샘플에서는 AsyncPattern 속성을 true로 설정합니다. 이 속성 설정을 .NET Framework 비동기 패턴 구현과 함께 사용하면 런타임에서 작업이 비동기적으로 호출됩니다.

서비스 구현에서 이 패턴을 사용하는 일반적인 이유는 디스크 액세스, 데이터베이스 액세스 또는 다른 서비스 호출과 같은 시간이 많이 걸리는 입출력 작업을 수행할 때 메시지 처리 스레드를 확보할 수 있기 때문입니다. 이 샘플에서는 IAsyncResult 구현을 사용하여 파일 입출력 작업을 래핑하는 방법을 보여 줍니다. MathAsyncResult 클래스 구현을 위한 기본 클래스를 다시 사용하여 IAsyncResult의 고유한 구현을 작성할 수 있습니다.

참고

이 샘플에서는 세션 바인딩에서 제공되는 순서 지정 동작을 방지하기 위해 PerCallMultiple이 사용됩니다. wsHttpBinding은 보안 컨텍스트를 설정하기 위해 기본적으로 세션을 사용합니다. 이 경우 클라이언트나 서비스에서 메시지 처리의 비동기 특성이 영향을 받지 않지만 응답 타이밍이 강조되고 클라이언트는 순차적 콜백 대신에 동시 콜백을 확인할 수 있습니다.

샘플을 실행하면 작업의 요청 및 응답이 클라이언트 콘솔 창에 표시됩니다. AddSubtract 요청은 비동기적으로 호출되므로 차단되지 않습니다. 그런 다음 MultiplyDivide 작업이 차단되고 해당 결과는 요청이 나갈 때 동시에 표시됩니다. 마지막으로 AddSubtract 작업의 결과가 클라이언트에 다시 도착할 때 표시됩니다. 클라이언트에서 비동기 콜백을 표시하기 위해 서비스의 AddSubtract 구현에서 sleep이 사용됩니다.

Add(100,15.99)
Subtract(145,76.54)
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714
Add Result: 115.99
Subtract Result: 68.46

AddSubtract와 같은 비동기 호출이 단일 스레드에서 처리된다는 것을 보여 주기 위해 서비스에서 스레드 ID가 사용됩니다. MultiplyDivide와 같은 비동기 호출은 둘 이상의 스레드와 관련됩니다. 서비스 출력은 다음과 같습니다.

Received Add Synchronously on ThreadID 11:  Sleeping for 3 seconds
Asynchronous call: BeginMultiply on ThreadID 12
Received Subtract Synchronously on ThreadID 12:  Sleeping for 3 seconds
IO thread for * operation on ThreadID 13
EndMultiply called on ThreadID 14
Asynchronous call: BeginDivide on ThreadID 14
IO thread for / operation on ThreadID 13
EndDivide called on ThreadID 14
Returning Add Result on ThreadID 11
Returning Subtract Result on ThreadID 12

.NET Framework 비동기 패턴은 클라이언트 또는 서비스나 둘 다에서 사용할 수 있습니다. 이 샘플에 표시된 것처럼 양쪽은 독립적입니다.

샘플을 설치, 빌드 및 실행하려면

  1. Windows Communication Foundation 샘플의 일회 설치 절차를 수행했는지 확인합니다.

  2. C# 또는 Visual Basic .NET 버전의 솔루션을 빌드하려면 Windows Communication Foundation 샘플 빌드의 지침을 따릅니다.

  3. 단일 컴퓨터 또는 다중 컴퓨터 구성에서 샘플을 실행하려면 Windows Communication Foundation 샘플 실행의 지침을 따릅니다.

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.