异步WCF服务调用阻止UI线程

时间:2015-04-18 05:34:25

标签: wcf asynchronous

我们在使用WPF应用程序进行后台调用时遇到问题。看起来,在较旧的计算机上(我们最常见的是在具有2GB RAM的Windows 7计算机上)我们的Web服务调用阻止UI 直到它完成。特别是对于一个电话,这是一个很大的问题,因为它可能需要五分钟才能完成。较新的计算机似乎处理得很好。

我们不关心通话所需的时间;我们只关心它没有阻止UI。我手边没有看到任何错误。

我们做错了什么,或者是2GB RAM上的Windows 7?是不是可以在这样的机器上解决它?

我们是否必须达到编写自定义TaskScheduler的水平以确保UI线程不被使用?我当然希望不会。

非常感谢任何输入。提前致谢。请参阅下面的代码示例。

DownloadBusinessEntityAsync是我们的应用程序调用的方法:

    #region DownloadBusinessEntity
    public async Task<BusinessEntity> DownloadBusinessEntityAsync(string businessEnityId)
    {
        BusinessEntity ret = new BusinessEntity();

        var client = new DownloadContext();

        try
        {
            Func<AsyncCallback, object, IAsyncResult> begin = (callback, state) => client.BeginDownloadBusinessEntity(businessEnityId, callback, state);
            Func<IAsyncResult, BusinessEntity> end = client.EndDownloadBusinessEntity;

            // ***THIS TAKES FIVE MINUTES TO FINISH***
            ret = await Task<BusinessEntity>.Factory.FromAsync(begin, end, null);

            if (client.State != CommunicationState.Faulted)
                client.Close();
            else
                client.Abort();
        }
        catch (Exception ex)
        {
            client.Abort();
        }

        return ret;
    }
    #endregion

DownloadContext是WCF客户端:

public partial class DownloadContext : ClientBase<IDownloadService>, IDownloadService, IDownloadContext, IDisposable
{
    public BusinessEntity DownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes)
    {
        return base.Channel.DownloadBusinessEntity(agencyId, activeHashCodes);
    }

    public IAsyncResult BeginDownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes, AsyncCallback callback, object asyncState)
    {
        return base.Channel.BeginDownloadBusinessEntity(agencyId, activeHashCodes, callback, asyncState);
    }

    public BusinessEntity EndDownloadBusinessEntity(IAsyncResult result)
    {
        return base.Channel.EndDownloadBusinessEntity(result);
    }
}

IDownloadService是WCF客户端实现的合同。

[ServiceContract(Namespace = "http://namespace.com/services/v1")]
public partial interface IDownloadService
{
    [OperationContract(ProtectionLevel=ProtectionLevel.Sign, Action="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntity", ReplyAction="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntityResponse")]
    BusinessEntity DownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes);

    [OperationContract(AsyncPattern=true, ProtectionLevel=ProtectionLevel.Sign, Action="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntity", ReplyAction="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntityResponse")]
    IAsyncResult BeginDownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes, AsyncCallback callback, object asyncState);

    BusinessEntity EndDownloadBusinessEntity(IAsyncResult result);

}

2 个答案:

答案 0 :(得分:2)

Microsoft在客户端HTTP连接(HttpWebRequest和朋友)的实现中存在一个已知问题:它们可以同步工作,包括DNS解析和(我相信)代理检测。即使对于异步请求,此工作也始终同步完成,并且可能需要一些时间,具体取决于您的网络配置。

我不确定WCF客户端是否共享此错误,但这很可能。最佳解决方法是根据usr's answer将其打包在Task.Run

答案 1 :(得分:1)

如果您只是不想阻止UI,那么将该工作移至后台线程。所有异步WCF内容都不是实现目标所必需的。类似的东西:

await Task.Run(() => DownloadBusinessEntityAsync(...));

如果您愿意,可以DownloadBusinessEntityAsync同步。