2012-12-19 19 views
9

當使用Background Transfer API時,我們必須迭代當前的數據傳輸,以便在應用程序終止後(即系統關閉)重新啓動應用程序。要獲得進度信息並能夠取消數據傳輸,必須使用AttachAsync連接它們。如何解決DownloadOperation的AttachAsync不會立即返回?

我的問題是AttachAsync只在數據傳輸完成時返回。這在某些情況下很有意義。但是當有多個數據傳輸時,列表中的下一個傳輸在當前連接完成之前不會啓動。我對這個問題的解決辦法是,以處理AttachAsync()AsTask()返回經典的方式任務(不使用等待,但延續):

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()); 
} 

它種工作(在實際的代碼中,我添加下載到列表框)。循環遍歷所有下載並執行StartAsync。但下載並非真正在同一時間開始。一次只能運行一個,並且只有當它完成時下一個纔會繼續。

這個問題的解決方案?

回答

3

整點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.... 
     } 
    } 
} 
+0

謝謝,但問題是不是任務。這是關於AttachAsync在下載完成之前不會返回的問題。我的解決方案確實有效我的問題的真正答案是,AttachAsync的這種行爲使我們能夠檢測下載何時完成。 –

+0

@Jürgen拜耳 - 也許我只是不明白你的問題在哪裏。當我在調試器中運行我的代碼時,執行'AttachAsync'的行會立即返回。等待的唯一地方是'while'循環,它應該等待 - 它處理下載的完成事件。 –

+0

AttachAsync立即返回是有目的的,因爲我沒有用await調用它,而是使用返回的任務來創建延續。問題是:如果一個應用程序在多個下載活動時被終止,我正在尋找一個解決方案,以在應用程序重新啓動時附加所有下載,而無需等待每個AttachAsync。我希望下載能夠像使用StartAsync多次啓動(當調用StartAsync的方法執行多次時)那樣執行,並行運行。但是這並沒有發生。使用AtttachAsync,一次只能運行一個下載。 –