我需要做些什么来防止客户端等待一个长WCF服务方法

本文关键字:一个 方法 服务 WCF 等待 做些什么 客户端 | 更新日期: 2023-09-27 18:17:58

我正在编写一个WCF webservice,它包含一个接受对象数组并将它们插入数据库的方法。这可能需要很长时间,所以我不能指望客户端等待。

我的同事认为我不需要做任何事情,异步调用我的服务是客户端的工作。我只是写了一个普通的方法。这听起来不太对我,虽然我希望这是真的,因为看WCF异步教程和SO问题只是困惑我到目前为止。

他正确吗?如果不是,我如何实际编写方法,以允许客户端异步调用该方法或避免挂起?

如果他是正确的(似乎是这样),那么定义异步方法([OperationContract (AsyncPattern=true)]、Begin、End等)的意义是什么?它是一种显式处理异步调用的方式,还是允许交互,还是什么?

我需要做些什么来防止客户端等待一个长WCF服务方法

应该落在客户端。他们必须防止自己的应用/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