异步操作可以通过使用下列三种方法之一:
基于任务的异步模式
基于事件的异步模式
IAsyncResult 异步模式
基于任务的异步模式是首选方式,因为它是最简单、最直接的执行异步操作。要使用此方法只需实现您的服务操作,并指定返回类型任务
public class SampleService:ISampleService
{
// ...
public async Task SampleMethodTaskAsync(string msg)
{
return Task.Factory.StartNew(() =>
{
return msg;
});
}
// ...
}
注意:
使用基于任务的异步模式时,当完成操作时出现异常,可能会引发 T:System.AggregateException。客户端或服务可能会发生此异常。
下面的代码段阐释如何声明使用事件基于异步模式的异步操作。
public class AsyncExample
{
// Synchronous methods.
public int Method1(string param);
public void Method2(double param);
// Asynchronous methods.
public void Method1Async(string param);
public void Method1Async(string param, object userState);
public event Method1CompletedEventHandler Method1Completed;
public void Method2Async(double param);
public void Method2Async(double param, object userState);
public event Method2CompletedEventHandler Method2Completed;
public void CancelAsync(object userState);
public bool IsBusy { get; }
// Class implementation not shown.
}
服务操作也可以按异步方式实现,具体方法是使用 .NET Framework 异步编程模式,并标记AsyncPattern 属性设置为true 的
通常,考虑到系统的异步特性,您不应依赖于线程。将数据传递到操作调度处理的各个阶段的最可靠方式是使用扩展。
定义一个异步执行(而不考虑它在客户端应用程序中的调用方式)的协定操作X:
使用 BeginOperation 和EndOperation 模式定义两个方法。
BeginOperation方法包括该操作的in 和ref 参数,并返回一个IAsyncResult 类型。
EndOperation方法包括一个IAsyncResult 参数以及out 和ref 参数,并返回操作的返回类型。
有关示例,请参见下面的方法。
int DoWork(string data, ref string inout, out string outonly)
若要创建异步操作,这两种方法应为:
[OperationContract(AsyncPattern=true)]
IAsyncResult BeginDoWork(string data, ref string inout, AsyncCallback callback, object state);
int EndDoWork(ref string inout, out string outonly, IAsyncResult result);
注意:
OperationContractAttribute属性仅适用于BeginDoWork 方法。所得到的协定具有一个名为DoWork 的 WSDL 操作。
WCF 客户端应用程序可使用之前介绍的三个异步调用模型中的任意一个。
1、使用基于任务模型时,只需调用使用等待关键字,如下面的代码片段中所示的操作。
await simpleServiceClient.SampleMethodTaskAsync(“hello, world”);
2、基于事件的异步模式只需添加事件处理程序,即可接收响应的通知 -- 将在用户界面线程上自动引发生成的事件。
若要使用此方法,请使用ServiceModel 元数据实用工具 (Svcutil.exe) 同时指定/async 和 /tcv:Version35 命令选项,如下面的示例所示。
svcutil http://localhost:8000/servicemodelsamples/service/mex /async /tcv:Version35
完成此操作后,Svcutil.exe 将生成带有事件基础结构的 WCF 客户端类,该事件基础结构使调用应用程序可以实现和分配事件处理程序,以便接收响应和采取相应的操作。
但是,基于事件的异步模型仅在 .NET Framework 3.5 版 中可用。此外,如果 WCF 客户端通道是使用System.ServiceModel.ChannelFactory<TChannel> 创建的,那么即使在 .NET Framework 3.5 中,也不支持该模型。使用 WCF 客户端通道对象时,必须使用System.IAsyncResult 对象异步调用操作。若要使用此方法,请使用ServiceModel 元数据实用工具 (Svcutil.exe) 并同时指定/async 命令选项,如下面的示例所示。
svcutil http://localhost:8000/servicemodelsamples/service/mex /async
这会生成一个服务协定,在该服务协定中,每个操作都作为
在任何一种情况下,即使服务是以同步方式实现的,应用程序也可以异步方式调用操作,就如同应用程序可以使用同一个模式以异步方式调用本地同步方法一样。操作的实现方式对于客户端而言无关紧要;当响应消息到达时,其内容会调度到客户端的异步 <End> 方法,并且客户端会检索相关信息。
还可以创建一个异步消息交换模式,在该模式下,单向操作(其OperationContractAttribute.IsOneWay 为true 的操作,该操作没有相关的响应)可以由客户端或服务独立于另一端来单向发送。(这会将双工消息交换模式用于单向消息。)在这种情况下,服务协定指定单向消息交换,即,任一端均可根据相应的情况以(或者不以)异步调用/实现形式来实现。通常,当服务协定是单向消息交换时,这些实现极有可能是异步的,因为在发送消息之后,应用程序不会等待答复,而是继续执行其他工作。
基于事件的异步模型设计准则规定,如果返回了多个值,则一个值会作为Result 属性返回,其他值会作为EventArgs 对象上的属性返回。因此产生的结果之一是,如果客户端使用基于事件的异步命令选项导入元数据,且该操作返回多个值,则默认的EventArgs 对象将返回一个值作为Result 属性,返回的其余值是EventArgs 对象的属性。
如果要将消息对象作为 Result 属性来接收并要使返回的值作为该对象上的属性,请使用/messageContract 命令选项。这会生成一个签名,该签名会将响应消息作为EventArgs 对象上的Result 属性返回。然后,所有内部返回值就都是响应消息对象的属性了。
转自:http://msdn.microsoft.com/zh-cn/library/ms734701.aspx