如何使用await包装方法调用?

时间:2013-02-18 23:03:54

标签: c# methods proxy wrapper async-await

所有对服务的调用都应通过个人频道进行。因此,所有可以访问服务器代理的方法都应该如下所示:

public async Task<SDRLocation[]> FindLocationsAsync(string searchString)
    {
        ChannelFactory<IQueryService> channel = new ChannelFactory<IQueryService>("SomeServ_IQuery");
        channel.Open();
        SomeProxy = channel.CreateChannel();
        Location[] locationEntitiesFound = await SomeProxy.FindLocationsAsync(searchString);
        ((IChannel)SomeProxy ).Close();

        return locationEntitiesFound.Select(x => new SDRLocation(x)).ToArray();
    }

但是因为我有很多像这样的服务调用的方法,所以我试图避免代码重复并创建这个方法包装器:

public TResult HandleServiceCall<TResult>(Func<IPlantOrgQueryService, TResult> serviceMethod)
    {
        ChannelFactory<IQueryService> channel = new ChannelFactory<IQueryService>("SomeServ_IQuery");
        channel.Open();
        IQueryService newProxy = channel.CreateChannel();
        TResult results = serviceMethod(newProxy);
        ((IChannel)newProxy).Close();

         return results;
    }

现在我希望到处都可以这样打电话:

public async Task<SDRLocation[]> FindLocationsAsync(string searchString)
    {
        Location[] locationEntitiesFound = await HandleServiceCall(x => x.FindLocationsAsync(searchString));

        return locationEntitiesFound.Select(x => new SDRLocation(x)).ToArray();
    }

但我最终得到错误“通信对象,System.ServiceModel.Channels.ClientReliableDuplexSessionChannel,因为它已被中止而不能用于通信。”

不明白什么是错误的,因为没有HandleServiceCall的方法可以正常工作......

请帮助

1 个答案:

答案 0 :(得分:1)

TResult的类型会让你知道什么是错的。它是Task<Location[]>。所以你在异步调用完成之前处理代理(通过Close)。

在调用await之前,修复是Task Close,就像原始代码一样。这应该可以解决问题:

public async Task<TResult> HandleServiceCall<TResult>(Func<IPlantOrgQueryService, Task<TResult>> serviceMethod)
{
    ChannelFactory<IQueryService> channel = new ChannelFactory<IQueryService>("SomeServ_IQuery");
    channel.Open();
    IQueryService newProxy = channel.CreateChannel();
    TResult results = await serviceMethod(newProxy);
    ((IChannel)newProxy).Close();

     return results;
}