我需要做些什么来防止客户端等待一个长WCF服务方法
本文关键字:一个 方法 服务 WCF 等待 做些什么 客户端 | 更新日期: 2023-09-27 18:17:58
我正在编写一个WCF webservice,它包含一个接受对象数组并将它们插入数据库的方法。这可能需要很长时间,所以我不能指望客户端等待。
我的同事认为我不需要做任何事情,异步调用我的服务是客户端的工作。我只是写了一个普通的方法。这听起来不太对我,虽然我希望这是真的,因为看WCF异步教程和SO问题只是困惑我到目前为止。
他正确吗?如果不是,我如何实际编写方法,以允许客户端异步调用该方法或避免挂起?
如果他是正确的(似乎是这样),那么定义异步方法([OperationContract (AsyncPattern=true)]、Begin、End等)的意义是什么?它是一种显式处理异步调用的方式,还是允许交互,还是什么?
它应该落在客户端。他们必须防止自己的应用/UI挂起。
让客户端异步调用你的方法。如果它们使用的是服务引用,那么所有的方法/事件都会自动生成。
myWcfClient.myMethodCompleted
+= new EventHandler<myMethodCompletedEventArgs>(myCallBack);
myWcfClient.myMethodAsync(args);
public void myCallback(object sender, myMethodCompletedEventArgs e)
{
var myResult = e.Result;
}
如果您的客户端不关心服务调用发生了什么,您需要一个简单的触发并忘记操作,您可以做到这一点。
AsyncPattern属性告诉运行时你的操作实现了。net框架异步方法设计模式。在这里看到的。如果您希望您的客户机应用程序知道服务调用发生了什么,那么您可以使用此模式。还有其他方法可以获得结果。
这只是在客户端,我跳过了旧的事件驱动的异步bleh模式,并用async-await模式代替它。不等待webmethod异步调用,阻塞UI…甚至不属于这个世纪;)
如果你正在使用。net 4.5+,你将免费获得async-await模式(除非wp8,你仍然需要包装它)。异步方法应该已经通过服务可用。如果您使用的是旧框架,我推荐使用AsyncBridge,它允许您在这种情况下使用async-await模式。另一种选择是坚持旧的事件驱动异步噩梦。下面的例子是只有当你使用c# 5.0或从不时才可能。
确保从一个非异步方法启动一个新线程
Task.Factory.StartNew(client.DoSomethingAsync("blabla") ).ContinueWith(...);
最后一部分在你的方法完成后运行,检查完成代码的异常等。
或者在一些异步方法中
public async Task<string> DoSomethingAsync(String text) {
// Exception handling etc
return await client.DoSomethingAsync(text);
}
将APM封装为async-await模式:
public class ServiceWrapper : IServiceWrapper
{
readonly YourServiceClient client;
public ServiceWrapper(YourServiceClient client)
{
this.client = client;
}
public async Task<string> DoSomethingAsync(string someParameter)
{
return await Task<string>.Factory.FromAsync(client.BeginDoSomeStuff, client.EndDoSomeStuff, someParameter, new object());
}
}
编辑打开和关闭包装服务中的连接。(我没有我的devbox可用,但这应该工作)。
public class ServiceWrapper : IServiceWrapper
{
EndpointAddress address;
public ServiceWrapper(EndpointAddress clientAddress)
{
address = clientAddress;
}
public async Task<string> DoSomethingAsync(string someParameter)
{
// handle exceptions etc here, can be done some cleaner..
var client = new YourServiceClient();
client.Endpoint.Address = address.Address; // can skip this..
await client.OpenAsync()
var res = await Task<string>.Factory.FromAsync(client.BeginDoSomeStuff, client.EndDoSomeStuff, someParameter, new object());
await client.CloseAsync();
return res;
}
}
最后一件事我不确定你是如何生成代理的,如果你使用vs,请确保在配置服务时挂钩允许异步方法的复选框。如果您使用svcutil,请添加适当的标志。
Async-await模式旧的事件驱动异步模式
希望有帮助,
欢呼,
Stian