分享

[WCF 学习笔记] 7. 异步调用

 隐形的翅膀 2007-11-23

 

[ 2007-04-01 20:59:13 | 作者: yuhen ]
字号: | |
WCF 的异步调用是基于消息交换(Message Exchange)来实现的,和我们通常使用委托来实现异步调用有所不同。

编写步骤:

1. 创建服务契约。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
  [OperationContract]
  int Add(int a, int b);
}

2. 为契约方法添加异步版本。

我们为 Add 方法添加了 BeginAdd 和 EndAdd 两个在 .NET SDK 中 "常见" 的异步操作方法。注意 BeginAdd 方法中我们添加了异步声明,而 EndAdd 方法没有。还有就是要注意异步版本方法的参数。
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculate
{
  [OperationContract]
  int Add(int a, int b);

  [OperationContract(AsyncPattern=true)]
  IAsyncResult BeginAdd(int a, int b, AsyncCallback callBack, object state);

  int EndAdd(IAsyncResult ar);
}

3. 实现服务契约。

你可能注意到了,我们并没有创建 Add 的委托原型,也没有 "真正" 实现 BeginAdd 和 EndAdd。这是因为消息交换会 "异步" 调用 Add 方法,所有的异步版本方法只是用来创建消息声明而已。
public class CalculateService : ICalculate
{
  public int Add(int a, int b)
  {
    Thread.Sleep(5000);
    Console.WriteLine(OperationContext.Current.SessionId);
    return a + b;
  }

  public IAsyncResult BeginAdd(int a, int b, AsyncCallback callBack, object state)
  {
    throw new Exception("The method or operation is not implemented.");
  }

  public int EndAdd(IAsyncResult ar)
  {
    throw new Exception("The method or operation is not implemented.");
  }
}

4. 我们给一个完整版本,看看执行结果。
[ServiceContract]
public interface ICalculate
{
  [OperationContract]
  int Add(int a, int b);

  [OperationContract(AsyncPattern = true)]
  IAsyncResult BeginAdd(int a, int b, AsyncCallback callBack, object state);

  int EndAdd(IAsyncResult ar);
}

public class CalculateService : ICalculate
{
  public int Add(int a, int b)
  {
    Console.WriteLine("服务器方法 Add 开始执行: {0}", DateTime.Now);
    try
    {
      Thread.Sleep(5000);
      return a + b;
    }
    finally
    {
      Console.WriteLine("服务器方法 Add 执行完成: {0}", DateTime.Now);
    }
  }

  public IAsyncResult BeginAdd(int a, int b, AsyncCallback callBack, object state)
  {
    throw new Exception("The method or operation is not implemented.");
  }

  public int EndAdd(IAsyncResult ar)
  {
    throw new Exception("The method or operation is not implemented.");
  }
}

public class WcfTest
{
  public static void Test()
  {
    AppDomain.CreateDomain("Server").DoCallBack(delegate
    {
      ServiceHost host = new ServiceHost(typeof(CalculateService));
      host.AddServiceEndpoint(typeof(ICalculate), new WSHttpBinding(),
       "http://localhost:8080/calc");

      host.Open();
    });

    ICalculate channel = ChannelFactory<ICalculate>.CreateChannel(new WSHttpBinding(),
     new EndpointAddress("http://localhost:8080/calc"));

    using (channel as IDisposable)
    {
      Console.WriteLine("客户端调用 BeginAdd: {0}", DateTime.Now);
      IAsyncResult ar = channel.BeginAdd(1, 2, delegate { Console.WriteLine("CallBack..."); }, null);
      Console.WriteLine("客户端调用 BeginAdd 完成: {0}", DateTime.Now);
      Console.WriteLine(channel.EndAdd(ar));
      Console.WriteLine("客户端调用 EndAdd 完成: {0}", DateTime.Now);
    }
  }
}

输出:
客户端调用 BeginAdd: 2007-4-1 20:56:47
客户端调用 BeginAdd 完成: 2007-4-1 20:56:47
服务器方法 Add 开始执行: 2007-4-1 20:56:49
服务器方法 Add 执行完成: 2007-4-1 20:56:54
3
客户端调用 EndAdd 完成: 2007-4-1 20:56:55
CallBack...

最后需要注意的是,我们必须使用支持 Session 的 Binding 对象 (BasicHttpBinding 会抛出异常)。

附:其实最简单的办法不是手工添加 AsyncPattern / BeginXXX / EndXXX,而是手工使用 svcutil.exe 生成客户端代理,记住加上 "/async" 参数。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多