WCF - IsOneWay 和异步的区别

在某些博客文章里,直接将 IsOneWay 称为 "异步方法"。虽然多数时候不会对开发带来什么问题,但深究起来,这两者是不同的。接下来,我们做个试验。将同一个服务契约分别用 IsOneWay 和异步进行实现,客户端使用多线程模拟并发调用,并使用 ServiceThrottlingBehavior (也可以使用 InstanceContextMode.Single) 进行并发控制。注意对比输出结果,我们就会发现其不同之处。

IsOneWay版本

[ServiceContract]
public interface IService
{
  [OperationContract(IsOneWay=true)]
  void Test();
}

public class MyService : IService
{
  public void Test()
  {
    Console.WriteLine("Service BeginAdd:{0}", DateTime.Now);
    Thread.Sleep(5000);
    Console.WriteLine("Service EndAdd:{0}", DateTime.Now);
  }
}

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

      ServiceThrottlingBehavior throttling = new ServiceThrottlingBehavior();
      throttling.MaxConcurrentInstances = 1;
      host.Description.Behaviors.Add(throttling);

      host.Open();
    });

    for (int i = 0; i < 3; i++)
    {
      new Thread(delegate()
      {
        IService channel = ChannelFactory<IService>.CreateChannel(new WSHttpBinding(),
         new EndpointAddress("http://localhost:8080/myservice"));

        using (channel as IDisposable)
        {
          Console.WriteLine("Client {0} BeginAdd:{1}",
            Thread.CurrentThread.ManagedThreadId, DateTime.Now);

          channel.Test();

          Console.WriteLine("Client {0} BeginAdd End:{1}",
            Thread.CurrentThread.ManagedThreadId, DateTime.Now);
        }
      }).Start();
    }
  }
}


输出:
Client 15 BeginAdd:2007-4-19 10:51:39
Client 14 BeginAdd:2007-4-19 10:51:39
Client 16 BeginAdd:2007-4-19 10:51:39
Client 16 BeginAdd End:2007-4-19 10:51:40
Service BeginAdd:2007-4-19 10:51:40
Service EndAdd:2007-4-19 10:51:45

Client 14 BeginAdd End:2007-4-19 10:51:46
Service BeginAdd:2007-4-19 10:51:46
Service EndAdd:2007-4-19 10:51:51
Service BeginAdd:2007-4-19 10:51:51

Client 15 BeginAdd End:2007-4-19 10:51:51
Service EndAdd:2007-4-19 10:51:56

异步版本

[ServiceContract]
public interface IService
{
  [OperationContract]
  void Test();

  [OperationContract(AsyncPattern = true)]
  IAsyncResult BeginTest(AsyncCallback callBack, object state);

  void EndTest(IAsyncResult ar);
}

public class MyService : IService
{
  public void Test()
  {
    Console.WriteLine("Service BeginAdd:{0}", DateTime.Now);
    Thread.Sleep(5000);
    Console.WriteLine("Service EndAdd:{0}", DateTime.Now);
  }

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

  public void EndTest(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(MyService));
      host.AddServiceEndpoint(typeof(IService), new WSHttpBinding(), "http://localhost:8080/myservice");

      ServiceThrottlingBehavior throttling = new ServiceThrottlingBehavior();
      throttling.MaxConcurrentInstances = 1;
      host.Description.Behaviors.Add(throttling);

      host.Open();
    });

    for (int i = 0; i < 3; i++)
    {
      new Thread(delegate()
      {
        IService channel = ChannelFactory<IService>.CreateChannel(new WSHttpBinding(),
         new EndpointAddress("http://localhost:8080/myservice"));

        using (channel as IDisposable)
        {
          Console.WriteLine("Client {0} BeginAdd:{1}",
            Thread.CurrentThread.ManagedThreadId, DateTime.Now);

          IAsyncResult ar = channel.BeginTest(null, null);

          Console.WriteLine("Client {0} BeginAdd End:{1}",
            Thread.CurrentThread.ManagedThreadId, DateTime.Now);

          channel.EndTest(ar);
        }
      }).Start();
    }
  }
}


输出:
Client 14 BeginAdd:2007-4-19 10:53:56
Client 16 BeginAdd:2007-4-19 10:53:56
Client 15 BeginAdd:2007-4-19 10:53:56
Client 16 BeginAdd End:2007-4-19 10:53:56
Client 14 BeginAdd End:2007-4-19 10:53:56
Client 15 BeginAdd End:2007-4-19 10:53:56
Service BeginAdd:2007-4-19 10:53:59
Service EndAdd:2007-4-19 10:54:04
Service BeginAdd:2007-4-19 10:54:04
Service EndAdd:2007-4-19 10:54:09
Service BeginAdd:2007-4-19 10:54:09
Service EndAdd:2007-4-19 10:54:14


通 过对比,我们发现异步方法 BeginXXX 调用并不受并发控制影响,调用后直接返回控制权;而 IsOneWay 则不同,它被阻塞直到服务方法获得执行才会返回(当然,没有等待服务方法执行完成)。这点区别在处理并发性能上,可能带来不同的效果,了解 IsOneWay 和异步的差别能让我们避免一些意外的问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值