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


Как асинхронно реализовывать операции службы

В приложениях Windows Communication Foundation (WCF) операция службы может быть реализована асинхронно или синхронно без жесткого задания способа вызова клиентом. Например, асинхронные операции службы могут вызываться синхронно или синхронные операции службы могут вызываться асинхронно. Пример асинхронного вызова операции из клиентского приложения см. в разделе Как асинхронно вызывать операции службы WCF. Дополнительные сведения синхронных и асинхронных режимах см. в разделах Создание контрактов служб и Синхронные и асинхронные операции. В этом разделе описывается базовая структура асинхронной операции службы, код не завершен. Полный образец стороны службы и клиента приведен в разделе Асинхронное взаимодействие.

Асинхронная реализация операции службы

  1. В контракте службы объявите пару асинхронных методов в соответствии с рекомендациями по асинхронной разработке для платформы .NET. Метод Begin принимает параметр, объект обратного вызова и объект состояния, а возвращает System.IAsyncResult; соответствующий метод End принимает System.IAsyncResult и возвращает возвращаемое значение. Дополнительные сведения об асинхронных вызовах см. в разделе Asynchronous Programming Design Patterns.

  2. Пометьте метод Begin пары асинхронных методов атрибутом System.ServiceModel.OperationContractAttribute и задайте для свойства System.ServiceModel.OperationContractAttribute.AsyncPattern значение true. Например, приведенный ниже код выполняет шаги 1 и 2.

      <OperationContractAttribute(AsyncPattern:=True)> _
      Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult
    
      ' Note: There is no OperationContractAttribute for the end method.
      Function EndServiceAsyncMethod(ByVal result As IAsyncResult) As String
    End Interface
    
      [OperationContractAttribute(AsyncPattern=true)]
      IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState);
    
      // Note: There is no OperationContractAttribute for the end method.
      string EndServiceAsyncMethod(IAsyncResult result);
    }
    
  3. Реализуйте пару методов Begin/End в классе своей службы в соответствии с рекомендациями по асинхронной разработке. Например, в следующем примере кода показана реализация, в которой строка записывается в консоль как в части Begin, так и в части End асинхронной операции службы, и возвращаемое значение операции End возвращается клиенту. Полный пример кода см. в подразделе "Пример".

Пример

В следующих примерах кода показаны:

  1. Интерфейс контракта службы с:

    1. Синхронной операцией SampleMethod.

    2. Асинхронной операцией BeginSampleMethod.

    3. Парой асинхронных операций BeginServiceAsyncMethod/EndServiceAsyncMethod.

  2. Реализацией службы с использованием объекта System.IAsyncResult.

Imports System
Imports System.Collections.Generic
Imports System.ServiceModel
Imports System.Text
Imports System.Threading

Namespace Microsoft.WCF.Documentation
  <ServiceContractAttribute(Namespace:="http://microsoft.wcf.documentation")> _
  Public Interface ISampleService

    <OperationContractAttribute> _
    Function SampleMethod(ByVal msg As String) As String

    <OperationContractAttribute(AsyncPattern := True)> _
    Function BeginSampleMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult

    'Note: There is no OperationContractAttribute for the end method.
    Function EndSampleMethod(ByVal result As IAsyncResult) As String

    <OperationContractAttribute(AsyncPattern:=True)> _
    Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult

    ' Note: There is no OperationContractAttribute for the end method.
    Function EndServiceAsyncMethod(ByVal result As IAsyncResult) As String
  End Interface

  Public Class SampleService
      Implements ISampleService
    #Region "ISampleService Members"

    Public Function SampleMethod(ByVal msg As String) As String Implements ISampleService.SampleMethod
      Console.WriteLine("Called synchronous sample method with ""{0}""", msg)
         Return "The sychronous service greets you: " & msg
    End Function

    ' This asynchronously implemented operation is never called because 
    ' there is a synchronous version of the same method.
    Public Function BeginSampleMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult Implements ISampleService.BeginSampleMethod
      Console.WriteLine("BeginSampleMethod called with: " & msg)
      Return New CompletedAsyncResult(Of String)(msg)
    End Function

    Public Function EndSampleMethod(ByVal r As IAsyncResult) As String Implements ISampleService.EndSampleMethod
      Dim result As CompletedAsyncResult(Of String) = TryCast(r, CompletedAsyncResult(Of String))
      Console.WriteLine("EndSampleMethod called with: " & result.Data)
      Return result.Data
    End Function

    Public Function BeginServiceAsyncMethod(ByVal msg As String, ByVal callback As AsyncCallback, ByVal asyncState As Object) As IAsyncResult Implements ISampleService.BeginServiceAsyncMethod
      Console.WriteLine("BeginServiceAsyncMethod called with: ""{0}""", msg)
      Return New CompletedAsyncResult(Of String)(msg)
    End Function

    Public Function EndServiceAsyncMethod(ByVal r As IAsyncResult) As String Implements ISampleService.EndServiceAsyncMethod
      Dim result As CompletedAsyncResult(Of String) = TryCast(r, CompletedAsyncResult(Of String))
      Console.WriteLine("EndServiceAsyncMethod called with: ""{0}""", result.Data)
      Return result.Data
    End Function
    #End Region
  End Class

  ' Simple async result implementation.
  Friend Class CompletedAsyncResult(Of T)
      Implements IAsyncResult
    Private data_Renamed As T

    Public Sub New(ByVal data As T)
        Me.data_Renamed = data
    End Sub

    Public ReadOnly Property Data() As T
        Get
            Return data_Renamed
        End Get
    End Property

    #Region "IAsyncResult Members"
    Public ReadOnly Property AsyncState() As Object Implements IAsyncResult.AsyncState
        Get
            Return CObj(data_Renamed)
        End Get
    End Property

    Public ReadOnly Property AsyncWaitHandle() As WaitHandle Implements IAsyncResult.AsyncWaitHandle
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property

    Public ReadOnly Property CompletedSynchronously() As Boolean Implements IAsyncResult.CompletedSynchronously
        Get
            Return True
        End Get
    End Property

    Public ReadOnly Property IsCompleted() As Boolean Implements IAsyncResult.IsCompleted
        Get
            Return True
        End Get
    End Property
    #End Region
  End Class
End Namespace
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
using System.Threading;

namespace Microsoft.WCF.Documentation
{
  [ServiceContractAttribute(Namespace="http://microsoft.wcf.documentation")]
  public interface ISampleService{

    [OperationContractAttribute]
    string SampleMethod(string msg);

    [OperationContractAttribute(AsyncPattern = true)]
    IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState);

    //Note: There is no OperationContractAttribute for the end method.
    string EndSampleMethod(IAsyncResult result);

    [OperationContractAttribute(AsyncPattern=true)]
    IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState);

    // Note: There is no OperationContractAttribute for the end method.
    string EndServiceAsyncMethod(IAsyncResult result);
  }

  public class SampleService : ISampleService
  {
    #region ISampleService Members

    public string  SampleMethod(string msg)
    {
      Console.WriteLine("Called synchronous sample method with \"{0}\"", msg);
        return "The sychronous service greets you: " + msg;
    }

    // This asynchronously implemented operation is never called because 
    // there is a synchronous version of the same method.
    public IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState)
    {
      Console.WriteLine("BeginSampleMethod called with: " + msg);
      return new CompletedAsyncResult<string>(msg);
    }

    public string EndSampleMethod(IAsyncResult r)
    {
      CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>;
      Console.WriteLine("EndSampleMethod called with: " + result.Data);
      return result.Data;
    }

    public IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState) 
    {
      Console.WriteLine("BeginServiceAsyncMethod called with: \"{0}\"", msg);
      return new CompletedAsyncResult<string>(msg);
    }

    public string EndServiceAsyncMethod(IAsyncResult r)
    {
      CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>;
      Console.WriteLine("EndServiceAsyncMethod called with: \"{0}\"", result.Data);
      return result.Data;
    }
    #endregion
  }

  // Simple async result implementation.
  class CompletedAsyncResult<T> : IAsyncResult
  {
    T data;

    public CompletedAsyncResult(T data)
    { this.data = data; }

    public T Data
    { get { return data; } }

    #region IAsyncResult Members
    public object AsyncState
    { get { return (object)data; } }

    public WaitHandle AsyncWaitHandle
    { get { throw new Exception("The method or operation is not implemented."); } }

    public bool CompletedSynchronously
    { get { return true; } }

    public bool IsCompleted
    { get { return true; } }
    #endregion
  }
}

См. также

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

Создание контрактов служб
Синхронные и асинхронные операции