我正在编写一个WCF Web服务,其中包含一个接受对象数组并将它们插入数据库的方法。这可能需要很长时间,所以我不能指望客户等待。
我的同事认为我不需要做任何事情,客户的工作是异步调用我的服务。我只是写一个普通的方法。这听起来不对我,虽然我希望它是正确的,因为查看WCF异步教程和SO问题到目前为止让我感到困惑。
他是对的吗?如果没有,我如何以允许客户端异步调用方法或以其他方式避免挂起的方式实际编写方法?
如果他是正确的(似乎是这种情况),那么定义异步方法([OperationContract(AsyncPattern = true)],Begin,End等等是什么意思。它是一种显式处理异步调用,或允许交互,还是什么?
的方式答案 0 :(得分:1)
应该落在客户端。他们必须阻止他们的app / UI挂起。
让您的客户端异步调用您的方法。如果他们使用服务引用,则会自动生成所有方法/事件。
myWcfClient.myMethodCompleted
+= new EventHandler<myMethodCompletedEventArgs>(myCallBack);
myWcfClient.myMethodAsync(args);
public void myCallback(object sender, myMethodCompletedEventArgs e)
{
var myResult = e.Result;
}
答案 1 :(得分:1)
如果您的客户不关心服务电话会发生什么,您需要一个简单的点火操作,您可以执行this。
AsyncPattern属性告诉运行时您的操作实现了.NET Framework异步方法设计模式。 See here。如果您希望客户端应用程序知道您的服务调用发生了什么,那么您可以使用此模式。还有其他方法可以获得结果。
答案 2 :(得分:-1)
这只是在客户端,我已经跳过旧的事件驱动的async 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添加适当的标志。
Old event driven async pattern
希望它有所帮助,
干杯,
了Stian