我有一个通用应用程序,可更新来自Internet源的多个对象。为了更新进度指示器并防止重复请求,我有以下逻辑。异步/等待链挂起或死锁
在刷新按钮:
foreach (var package in Packages.Where(item => !item.Received))
{
RefeshPackage(package);
}
其中在列表中呼吁RefreshPackage每个包:
private async Task RefeshPackage(PackageModel package)
{
if (Tasks.Contains(package.Id)) return;
Tasks.Add(package.Id);
await DownloadAndUpdate(package);
Tasks.Remove(package.Id);
Refresh.RaiseCanExecuteChanged();
}
这对于每个包调用下载升级:
private async Task DownloadAndUpdate(PackageModel package)
{
var response = await webService.GetPackageStages(package.Id);
if (response != null)
{
switch (response.Status)
{
case 200:
package.UpdateStages(response.Stages);
break;
case 500:
//package doesn't exist or website down
break;
default:
break;
}
}
else
{
//no network/timed out
}
}
这对于要求GetPackageStages每个包装:
public async Task<ResponseData> GetPackageStages(string id)
{
var requestUri = string.Concat(MyUri, id);
var client = new HttpClient();
client.Timeout = new TimeSpan(0,0,5);
try
{
var response = await client.GetAsync(requestUri);
if(response.StatusCode == System.Net.HttpStatusCode.OK)
{
//process response
}
catch (Exception e)
{
return null;
}
finally
{
client.Dispose();
}
}
悬/锁死总是发生在最后一个函数,在该行:
await client.GetAsync(requestUri);
有时它挂在这里永远有时它工作得很好。我已经阅读了很多关于死锁的其他解答,常见的解决方案是,使用异步/等待(我已经在做)或使用。配置等待(false)无处不在(我已经做了没有成功)。
是否还有别的我失踪或应该以不同的方式构建我的代码?我已经用完了想法/解决方案。任何帮助,将不胜感激。
'RefreshPackage'是一种异步方法。你为什么不对外部'foreach'循环中产生的'Task'做任何事情?即使你不想等待它,至少你应该观察它的错误('.ContinueWith(,... TaskContinuationOptions.OnlyOnFaulted)')。 – 2015-03-02 12:21:52
你会怎么知道?你不等待'RefeshPackage(package)'的结果;' – Jodrell 2015-03-02 12:22:19
它是挂起还是去//没有网络/超时情况? – gabba 2015-03-02 12:24:13