WCF异步调用:
WCF可以通过使用下列三种方法之一实现异步操作:
1、基于任务的异步模式:(使用Task实现)
基于任务的异步模式是实现异步操作的首选方法,因为它最简单且最直接。
2、基于事件的异步模式:(工具 (Svcutil.exe) 需要同时指定 /async 和 /tcv:Version35 命令选项)
基于事件的异步模型仅在 .NET Framework 版本 3.5 中可用。
3、IAsyncResult 异步模式:(工具 (Svcutil.exe) 需要指定 /async 命令选项)
本文以 IAsyncResult 异步模式 为例,在VS2013环境下测试通过。
示例代码一: 基本WCF异步方法
服务端:
[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.");
}
}
WCF配置文件:
<service name="WcfService2.CalculateService">
<endpoint address="" binding="netTcpBinding" contract="WcfService2.ICalculate"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/WcfService2/CalculateService/" />
<add baseAddress="net.tcp://localhost:8734/Design_Time_Addresses/WcfService2/CalculateService/" />
</baseAddresses>
</host>
</service>
客户端:
引用服务:在引用服务时,左下角点击“高级”按钮,勾选“生成异步操作”即可。
CalculateClient client = new CalculateClient();
//int result = client.Add(5, 7); // 同步方法
client.AddCompleted += client_AddCompleted;
client.AddAsync(3, 2); // 异步方法
private void client_AddCompleted(object sender, AddCompletedEventArgs e)
{
try
{
int result = e.Result;
CalculateClient client = (CalculateClient)sender;
if (client != null)
{
// 释放资源。
client.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
示例代码二: WCF异步返回其它类型数据,例如数组。
[ServiceContract]
public interface IService3
{
[OperationContractAttribute]
List<string> SampleMethod(int num);
[OperationContractAttribute(AsyncPattern = true)]
IAsyncResult BeginSampleMethod(int num, AsyncCallback callback, object asyncState);
//Note: There is no OperationContractAttribute for the end method.
List<string> EndSampleMethod(IAsyncResult result);
}
public class Service3 : IService3
{
public List<string> SampleMethod(int num)
{
List<string> list = new List<string>();
list.Add("aaa");
list.Add("bbb");
//Log.GetInstance().LogInfo(LogLevel.Message, "SampleMethod", "num: "+num.ToString());
return list;
}
public IAsyncResult BeginSampleMethod(int num, AsyncCallback callback, object asyncState)
{
// 经过测试,异步调用时,该方法未执行。
//Console.WriteLine("BeginSampleMethod called with: " + msg);
//return new CompletedAsyncResult<List<string>>();
//Log.GetInstance().LogInfo(LogLevel.Message, "BeginSampleMethod", "num: " + num.ToString());
throw new Exception("The method or operation is not implemented.");
}
public List<string> EndSampleMethod(IAsyncResult r)
{
// 经过测试,异步调用时,该方法未执行。
//CompletedAsyncResult<List<string>> result = r as CompletedAsyncResult<List<string>>;
//Console.WriteLine("EndSampleMethod called with: " + result.Data);
//return result.Data;
//Log.GetInstance().LogInfo(LogLevel.Message, "EndSampleMethod", "not.");
throw new Exception("The method or operation is not implemented.");
}
}
测试代码:
// 示例1:
//CalculateClient client = new CalculateClient();
////int result = client.Add(5, 7); // 同步方法
//client.AddCompleted += client_AddCompleted;
//client.AddAsync(3, 2); // 异步方法
// 示例2:
Service3Client client3 = new Service3Client();
string[] list = client3.SampleMethod(3); // 同步方法
client3.SampleMethodCompleted += client3_SampleMethodCompleted;
client3.SampleMethodAsync(3);// 异步方法
private void client3_SampleMethodCompleted(object sender, SampleMethodCompletedEventArgs e)
{
try
{
string[] message = e.Result;
Service3Client client = (Service3Client)sender;
if (client != null)
{
// 释放资源。
client.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
示例代码三: WCF异步返回其它类型数据,并带有 ref 和 out 参数
[ServiceContract]
public interface IService3
{
[OperationContractAttribute]
List<string> SampleMethod(int num, ref string inout, out string outonly);
[OperationContractAttribute(AsyncPattern = true)]
IAsyncResult BeginSampleMethod(int num, ref string inout, AsyncCallback callback, object asyncState);
//Note: There is no OperationContractAttribute for the end method.
List<string> EndSampleMethod(ref string inout, out string outonly, IAsyncResult result);
}
public class Service3 : IService3
{
public List<string> SampleMethod(int num, ref string inout, out string outonly)
{
List<string> list = new List<string>();
list.Add("aaa");
list.Add("bbb");
inout += " is ok.";
outonly = "this is " + inout;
//Log.GetInstance().LogInfo(LogLevel.Message, "SampleMethod", "num: "+num.ToString());
return list;
}
public IAsyncResult BeginSampleMethod(int num, ref string inout, AsyncCallback callback, object asyncState)
{
// 经过测试,异步调用时,该方法未执行。
//Console.WriteLine("BeginSampleMethod called with: " + msg);
//return new CompletedAsyncResult<List<string>>();
//Log.GetInstance().LogInfo(LogLevel.Message, "BeginSampleMethod", "num: " + num.ToString());
throw new Exception("The method or operation is not implemented.");
}
public List<string> EndSampleMethod(ref string inout, out string outonly, IAsyncResult result)
{
// 经过测试,异步调用时,该方法未执行。
//CompletedAsyncResult<List<string>> result = r as CompletedAsyncResult<List<string>>;
//Console.WriteLine("EndSampleMethod called with: " + result.Data);
//return result.Data;
//Log.GetInstance().LogInfo(LogLevel.Message, "EndSampleMethod", "not.");
throw new Exception("The method or operation is not implemented.");
}
}
调用方法:
// 示例3:
Service3Client client3 = new Service3Client();
string inout = "hello";
string outonly = string.Empty;
//string[] list = client3.SampleMethod(3, ref inout, out outonly); // 同步方法
client3.SampleMethodCompleted += client3_SampleMethodCompleted;
client3.SampleMethodAsync(3, inout, outonly);// 异步方法
private void client3_SampleMethodCompleted(object sender, SampleMethodCompletedEventArgs e)
{
try
{
string[] message = e.Result; // 返回值
string inout = e.inout; // ref 参数
string outonly = e.outonly; // out 参数
Service3Client client = (Service3Client)sender;
if (client != null)
{
// 释放资源。
client.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
说明:以上内容来源于网络与MSDN。