ChannelFactory 异步调用

来源:互联网 发布:想开淘宝店怎么注册 编辑:程序博客网 时间:2024/05/21 18:41

如果你和我一样,想当然用基于委托或事件异步模型来调用 WCF Operation。那么恭喜你,打破脑袋你也不会明白为啥 BeginInvoke() 没效果。

[ServiceContract]
interface IMyService
{
  [OperationContract]
  void Test();
}

class MyService : IMyService
{
  public void Test()
  {
    Console.WriteLine("Begin {0}...", DateTime.Now);
    Thread.Sleep(3000);
    Console.WriteLine("End {0}...", DateTime.Now);
  }
}

class Program
{
  private static void Client()
  {
    var binding = new BasicHttpBinding();
    var address = new EndpointAddress("http://localhost:90");
    var channel = ChannelFactory<IMyService>.CreateChannel(binding, address);

    using (channel as IDisposable)
    {
      var test = new Action(channel.Test);
      var ir = test.BeginInvoke(null, null); // ???? 为啥不起作用呢?

      Console.WriteLine("Test {0}...", DateTime.Now);

      test.EndInvoke(ir);
    }
  }

  private static void Server()
  {
    AppDomain.CreateDomain("Server").DoCallBack(() =>
    {
      var host = new ServiceHost(typeof(MyService), new Uri("http://localhost:90"));

      host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
      host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");
      host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

      host.Open();
    });
  }

  static void Main(string[] args)
  {
    Server();
    Client();

    Console.WriteLine("Press any key to exit...");
    Console.ReadKey(true);
    Environment.Exit(0);
  }
}


输出:
Begin 2008-6-2 16:20:32...
End 2008-6-2 16:20:35...
Test 2008-6-2 16:20:35...

从输出结果来看,很显然异步没 "异" 成。想了 N 久,也用独立线程尝试,很显然不是代码有问题。一番痛苦找寻后看到 MSDN 有这么一句话:

The event-driven asynchronous calling model is not supported when using a ChannelFactory.


火大!!!!!MSDN 给出了答案,就是要生成 "异步版本" 的代理契约。用 svcutil.exe 或者 VS 的导入工具,老老实实生成代理代码后,再来测试一下。

uploads/200806/02_162811_2.gif

 

uploads/200806/02_162639_1.gif

 

private static void Client()
{
  var binding = new BasicHttpBinding();
  var address = new EndpointAddress("http://localhost:90");
  var channel = ChannelFactory<global::Learn.CUI.ServiceReference1.IMyService>.CreateChannel(binding, address);

  using (channel as IDisposable)
  {
    var ir = channel.BeginTest(null, null); // 使用异步版本!

    Console.WriteLine("Test {0}...", DateTime.Now);

    channel.EndTest(ir);
  }
}


输出:

Test 2008-6-2 16:26:52...
Begin 2008-6-2 16:26:52...
End 2008-6-2 16:26:55...