다음을 통해 공유


방법: 채널 팩터리를 사용하여 비동기적으로 작업 호출

이 주제에서는 ChannelFactory<TChannel> 기반의 클라이언트 애플리케이션을 사용할 때 클라이언트가 서비스 작업에 비동기적으로 접근할 수 있는 방법에 대해 설명합니다. (개체를 System.ServiceModel.ClientBase<TChannel> 사용하여 서비스를 호출하는 경우 이벤트 기반 비동기 호출 모델을 사용할 수 있습니다. 자세한 내용은 방법: 비동기적으로 서비스 작업 호출을 참조하세요. 이벤트 기반 비동기 호출 모델에 대한 자세한 내용은 EAP(이벤트 기반 비동기 패턴)를 참조하세요.

이 항목의 서비스는 ICalculator 인터페이스를 구현합니다. 클라이언트는 이 인터페이스의 작업을 비동기적으로 호출할 수 있습니다. 즉, 같은 Add 작업은 두 가지 메서드로 분할되며BeginAdd, EndAdd 그 중 전자는 호출을 시작하고 후자는 작업이 완료될 때 결과를 검색합니다. 서비스에서 비동기적으로 작업을 구현하는 방법을 보여 주는 예제는 방법: 비동기 서비스 작업 구현을 참조하세요. 동기 및 비동기 작업에 대한 자세한 내용은 동기 및 비동기 작업을 참조하세요.

절차

WCF 서비스 작업을 비동기적으로 호출하려면

  1. 다음 명령에서와 같이 옵션을 사용하여 /async를 실행합니다.

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

    이렇게 하면 작업에 대한 서비스 계약의 비동기 클라이언트 버전이 생성됩니다.

  2. 다음 샘플 코드와 같이 비동기 작업이 완료되면 호출할 콜백 함수를 만듭니다.

    static void AddCallback(IAsyncResult ar)
    {
        double result = ((CalculatorClient)ar.AsyncState).EndAdd(ar);
        Console.WriteLine($"Add Result: {result}");
    }
    
    Private Shared Sub AddCallback(ByVal ar As IAsyncResult)
        Dim result = (CType(ar.AsyncState, CalculatorClient)).EndAdd(ar)
        Console.WriteLine("Add Result: {0}", result)
    End Sub
    
  3. 서비스 작업에 비동기적으로 액세스하려면 다음 샘플 코드와 같이 클라이언트를 Begin[Operation] 만들고 호출하고(예 BeginAdd:) 콜백 함수를 지정합니다.

    ChannelFactory<ICalculatorChannel> factory = new ChannelFactory<ICalculatorChannel>();
    ICalculatorChannel channelClient = factory.CreateChannel();
    
    // BeginAdd
    double value1 = 100.00D;
    double value2 = 15.99D;
    
    IAsyncResult arAdd = channelClient.BeginAdd(value1, value2, AddCallback, channelClient);
    Console.WriteLine($"Add({value1},{value2})");
    
    Dim factory As New ChannelFactory(Of ICalculatorChannel)()
    Dim channelClient As ICalculatorChannel = factory.CreateChannel()
    
    ' BeginAdd
    Dim value1 = 100.0R
    Dim value2 = 15.99R
    
    Dim arAdd As IAsyncResult = channelClient.BeginAdd(value1, value2, AddressOf AddCallback, channelClient)
    Console.WriteLine("Add({0},{1})", value1, value2)
    

    콜백 함수가 실행되면 클라이언트는 결과를 검색하기 위해 호출 End<operation> 합니다(예: EndAdd).

예시

이전 절차에서 사용되는 클라이언트 코드와 함께 사용되는 서비스는 다음 코드와 같이 인터페이스를 구현합니다 ICalculator . 서비스 쪽에서는 Add 이전 클라이언트 단계가 클라이언트에서 비동기적으로 호출되더라도 WCF(Windows Communication Foundation) 런타임에 의해 계약의 작업 및 Subtract 작업이 동기적으로 호출됩니다. MultiplyDivide 작업은 클라이언트가 동기적으로 호출하더라도 서비스 쪽에서 비동기적으로 서비스를 호출하기 위해 사용됩니다. 이 예제는 AsyncPattern 속성을 true로 설정합니다. 이 속성 설정은 .NET Framework 비동기 패턴의 구현과 함께 런타임에 작업을 비동기적으로 호출하도록 지시합니다.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface ICalculator
{
    [OperationContract]
    double Add(double n1, double n2);

    [OperationContract]
    double Subtract(double n1, double n2);

    //Multiply involves some file I/O so we'll make it Async.
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginMultiply(double n1, double n2, AsyncCallback callback, object state);
    double EndMultiply(IAsyncResult ar);

    //Divide involves some file I/O so we'll make it Async.
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginDivide(double n1, double n2, AsyncCallback callback, object state);
    double EndDivide(IAsyncResult ar);
}
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.Samples")> _
Public Interface ICalculator
    <OperationContract> _
    Function Add(ByVal n1 As Double, ByVal n2 As Double) As Double

    <OperationContract> _
    Function Subtract(ByVal n1 As Double, ByVal n2 As Double) As Double

    'Multiply involves some file I/O so we'll make it Async.
    <OperationContract(AsyncPattern:=True)> _
    Function BeginMultiply(ByVal n1 As Double, ByVal n2 As Double, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult
    Function EndMultiply(ByVal ar As IAsyncResult) As Double

    'Divide involves some file I/O so we'll make it Async.
    <OperationContract(AsyncPattern:=True)> _
    Function BeginDivide(ByVal n1 As Double, ByVal n2 As Double, ByVal callback As AsyncCallback, ByVal state As Object) As IAsyncResult
    Function EndDivide(ByVal ar As IAsyncResult) As Double
End Interface