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



我们的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);

}

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

我不确定WCF客户端是否共享这个错误,但很可能。最好的解决方法是根据usr的答案将其封装在Task.Run中。

如果您只是不想阻止UI,那么将工作转移到后台线程。实现您的目标并不需要所有异步WCF的东西。类似于:

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

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

最新更新