如何解决DownloadOperation的AttachAsync不会立即返回?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解决DownloadOperation的AttachAsync不会立即返回?相关的知识,希望对你有一定的参考价值。
当使用Background Transfer API时,我们必须迭代当前数据传输以在应用程序重新启动(即系统关闭)后重新启动它们。要获取进度信息并能够取消数据传输,必须使用AttachAsync附加它们。
我的问题是AttachAsync仅在数据传输完成时返回。这在某些情况下是有道理的。但是,当进行多次数据传输时,列表中的下一次传输将不会在当前连接完成之前启动。我对这个问题的解决方案是处理AttachAsync()的任务.AsTask()以经典的方式返回(不使用await而是continuation):
IReadOnlyList<DownloadOperation> currentDownloads =
await BackgroundDownloader.GetCurrentDownloadsAsync();
foreach (var downloadOperation in currentDownloads)
{
Task task = downloadOperation.AttachAsync().AsTask();
DownloadOperation operation = downloadOperation;
task.ContinueWith(_ =>
{
// Handle success
...
}, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.FromCurrentSynchronizationContext());
task.ContinueWith(_ =>
{
// Handle cancellation
...
}, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled,
TaskScheduler.FromCurrentSynchronizationContext());
task.ContinueWith(t =>
{
// Handle errors
...
}, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
}
它有点工作(在实际的代码中我将下载添加到ListBox)。循环遍历所有下载并执行StartAsync。但下载并非真正同时启动。每次只有一个运行,只有当它完成后,下一个继续运行。
解决这个问题的任何方法?
答案
Task
的重点是允许您选择并行操作。如果你await
然后你告诉代码序列化操作;如果你没有等待,那么你告诉代码要并行化。
您可以做的是将每个下载任务添加到列表中,告诉代码并行化。然后,您可以逐个等待任务完成。
怎么样的:
IReadOnlyList<DownloadOperation> currentDownloads =
await BackgroundDownloader.GetCurrentDownloadsAsync();
if (currentDownloads.Count > 0)
{
List<Task<DownloadOperation>> tasks = new List<Task<DownloadOperation>>();
foreach (DownloadOperation downloadOperation in currentDownloads)
{
// Attach progress and completion handlers without waiting for completion
tasks.Add(downloadOperation.AttachAsync().AsTask());
}
while (tasks.Count > 0)
{
// wait for ANY download task to finish
Task<DownloadOperation> task = await Task.WhenAny<DownloadOperation>(tasks);
tasks.Remove(task);
// process the completed task...
if (task.IsCanceled)
{
// handle cancel
}
else if (task.IsFaulted)
{
// handle exception
}
else if (task.IsCompleted)
{
DownloadOperation dl = task.Result;
// handle completion (e.g. add to your listbox)
}
else
{
// should never get here....
}
}
}
另一答案
我希望现在还不算太晚,但我确切地知道你在谈论什么。我还试图在应用程序启动时恢复所有下载。
经过几个小时的尝试,这是有效的解决方案。
诀窍是在攻击进度处理程序之前先让下载操作恢复。
downloadOperation.Resume();
await downloadOperation.AttachAsync().AsTask(cts.Token);
以上是关于如何解决DownloadOperation的AttachAsync不会立即返回?的主要内容,如果未能解决你的问题,请参考以下文章