WCF热门问题编程示例(4):WCF客户端如何异步调用WCF服务?
How to call WCF Service asynchronously?
【1】问题描述:
WCF客户端如何异步调用WCF服务?
How to call WCF Service asynchronously?
关于WCF如何实现异步调用的问题,论坛上出现了很多帖子,也有很多讨论的文章,包括MSDN也给出了详细的学习资料和示例代码。但是很多资料过于笼统,MSDN的例子有点复杂。而我们实际项目中,要实现的需求,往往十分简单,就是要在客户端实现对于WCF服务操作的异步调用,也就是call WCF Service asynchronously。
【2】资料收集:
这里收集一些关于WCF异步调用比较有用的参考资料和问题连接。其实关于WCF客户端异步调用WCF服务的帖子很多,很多讨论反而走了弯路,我们想要的就是简单的异步调用WCF服务操作的例子。这里给出一些比较有价值的参考资料:
【3】异步调用:
这里需要了解的一个重要概念就是异步调用机制,在.NET里的异步调用机制是十分重要的一个知识点。另外就是回调的概念,这里也会使用到。.Net中的异步调用实际使用的是异步委托。异步委托将要执行的方法提交到.Net的线程池,由线程池中的线程来执行异步调用。
【4】解决办法:
知道了.NET异步调用的机制以后,我们就可以来尝试解决这个问题。这里本质是一样的。但编码的过程有点差别。
- 当然,最容易理解的就是我们自己写代码来实现异步调用。
- 其次,Visual Studio 2008已经提供了这个支持。这个更加方便。我给出截图:
我们这里给出的示例过程呢,是基于手写客户端异步调用代码的。仅供参考,当然你也可以使用Visual Studio来帮助完成这个过程。
【5】服务端代码:
服务端代码的实现十分简单,这里我们依然使用早期WCF的代码,定义一个IWCFService契约,包含一个操作SayHello,这个操作实现的功能,就是接受一name参数,然后打印返回字符串给客户端,为了演示,这里会打印出时间信息。具体代码如下:
//1.服务契约
[ServiceContract(Namespace = "http://www.cnblogs.com/frank_xl/")]
public interface IWCFService
{
//操作契约
[OperationContract]
string SayHello(string name);}
//2.服务类,继承接口。实现契约
public class WCFService : IWCFService
{
//实现接口定义的方法
public string SayHello(string name)
{
Console.WriteLine("Call Operation at {0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"));
return string.Format("Hello {0}",name);
}
}
【6】客户端代码:
客户端的实现大部分代码与之前的没有区别,为了方便,我们可以在Visual Studio生成的代码基础上修改。当然也完全可以自己重写。 这里比较重要的一点,就是要实现异步调用需要的契约以及异步调用的方法。
【6.1】首先这里要实现支持异步调用的契约:
public interface IWCFService {
[System.ServiceModel.OperationContractAttribute(Action="http://www.cnblogs.com/frank_xl/IWCFService/SayHello", ReplyAction="http://www.cnblogs.com/frank_xl/IWCFService/SayHelloResponse")]
string SayHello(string name);[OperationContract(AsyncPattern = true)]
IAsyncResult BeginSayHello(string name, AsyncCallback callback, object asyncState);string EndSayHello(IAsyncResult result);
}
【6.2】支持异步调用的客户端代理类:
我们要在自己的WCFClient代理类里继承这个契约,并提供异步操作调用的实现,具体代码如下:
public string SayHello(string name) {
return base.Channel.SayHello(name);
}public IAsyncResult BeginSayHello(string name, AsyncCallback callback, object asyncState)
{
return Channel.BeginSayHello(name, callback, asyncState);
}public string EndSayHello(IAsyncResult result)
{
return Channel.EndSayHello(result);
}
【6.3】测试客户端代码:
客户端代码还有一点比较重要的地方,就是实现异步回调方法,这里我们在调用BeginSayHello方法的时候,不需要等待结果的返回,我们自己希望,WCF在调用完SayHello操作以后,执行一些必要的工作,比如显示返回结果,或者对返回的数据做更深入的处理,这里都需要使用到回调函数。我们也可以在回调方法里,来关闭WCF客户端,以释放资源。
例子代码如下:
/// <summary>
/// This class is defined for WCF Async Call Test
/// </summary>
public class WCFClientTest
{
static public WCFServiceClient wcfServiceProxy = null;
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Yellow;WCFClientTest client = new WCFClientTest();
wcfServiceProxy = new WCFServiceClient("WSHttpBinding_IWCFService");
string name = "Frank Xu Lei";
Console.WriteLine("Client Async Call begin at {0}",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"));
//开始异步调用Begin Call
wcfServiceProxy.BeginSayHello(name, client.OnCompletion, null);Console.WriteLine("press ENTER to exit…");
Console.Read();}
////回调方法,Callback method
void OnCompletion(IAsyncResult result)
{
string value = wcfServiceProxy.EndSayHello(result);
Console.WriteLine("Returned value is {0} at {1}",value, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"));
result.AsyncWaitHandle.Close();
wcfServiceProxy.Close();
Console.WriteLine("Asynchronous Calls is finished");
}
}
【7】运行结果:
这里启动宿主Host程序,然后运行WCF客户端即可,我们可以看到宿主端和客户端,异步调用操作的时间差别,打印窗口的截图如下:
【老徐的博客】
【网 站】:http://www.frankxulei.com/
【博 客】:http://www.cnblogs.com/frank_xl/
【中文论坛】:微软WCF中文技术论坛
【英文论坛】:微软WCF英文技术论坛