2012-12-19 18 views
9

Khi sử dụng API truyền tải nền, chúng tôi phải lặp qua chuyển dữ liệu hiện tại để bắt đầu lại khi ứng dụng khởi động lại sau khi chấm dứt (tức là tắt hệ thống). Để có được thông tin tiến bộ và để có thể hủy bỏ việc truyền dữ liệu, chúng phải được đính kèm bằng cách sử dụng AttachAsync.Làm thế nào để giải quyết rằng AttachAsync của một DownloadOperation không trở lại ngay lập tức?

Vấn đề của tôi là AttachAsync chỉ trả về khi quá trình truyền dữ liệu hoàn tất. Điều đó có ý nghĩa trong một số tình huống. Nhưng khi có nhiều chuyển dữ liệu, lần chuyển tiếp theo trong danh sách sẽ không được bắt đầu cho đến khi phần đính kèm hiện tại kết thúc. Giải pháp của tôi cho vấn đề này là để xử lý các nhiệm vụ mà AttachAsync() AsTask() trả về theo cách cổ điển (không sử dụng đang chờ đợi nhưng continuations):.

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

Nó loại công trình (trong mã thực tế tôi thêm tải xuống một ListBox). Vòng lặp lặp qua tất cả các lần tải xuống và thực thi StartAsync. Nhưng các bản tải xuống không thực sự bắt đầu cùng một lúc. Chỉ có một lần runninng tại một thời điểm và chỉ khi nó kết thúc tiếp theo.

Bất kỳ giải pháp nào cho vấn đề này?

Trả lời

3

Toàn bộ điểm Task là cho phép bạn có tùy chọn hoạt động song song. Nếu bạn await thì bạn đang yêu cầu mã để tuần tự hóa các hoạt động; nếu bạn không chờ đợi, thì bạn đang yêu cầu mã song song.

Việc bạn có thể làm là thêm từng tác vụ tải xuống vào danh sách, yêu cầu mã song song. Sau đó, bạn có thể đợi các tác vụ hoàn thành, từng cái một.

Làm thế nào về một cái gì đó như:

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

Cảm ơn, nhưng câu hỏi không phải là về Tasks. Đó là về sự cố mà AttachAsync không trả lại cho đến khi quá trình tải xuống hoàn tất. Giải pháp của tôi không hoạt động. Câu trả lời thực sự cho câu hỏi của tôi là hành vi này của AttachAsync cho phép chúng tôi phát hiện khi tải xuống hoàn tất. –

+0

@ Jürgen Bayer - Có lẽ tôi không hiểu vấn đề của bạn ở đâu. Khi tôi chạy mã của tôi ở trên trong trình gỡ rối, dòng mà 'AttachAsync' trả về ngay lập tức. Nơi duy nhất chờ đợi là vòng lặp while 'while' được chờ đợi - nó xử lý sự kiện hoàn thành của các lần tải xuống. –

+0

Phản hồi của AttachAsync ngay lập tức là vì mục đích vì tôi không gọi nó bằng cách chờ đợi nhưng sử dụng tác vụ được trả lại để tạo ra sự tiếp tục. Vấn đề là: Nếu một ứng dụng bị chấm dứt trong khi nhiều lần tải xuống đang hoạt động, tôi đang tìm kiếm giải pháp để đính kèm tất cả các bản tải xuống khi ứng dụng khởi động lại mà không cần đợi từng AttachAsync. Hy vọng của tôi là các bản tải xuống sau đó sẽ chạy song song giống như khi chúng bắt đầu nhiều lần bằng cách sử dụng StartAsync (khi phương thức gọi StartAsync được thực thi nhiều lần). Nhưng điều đó không xảy ra. Với AtttachAsync chỉ có một lần tải xuống chạy một lần. –

Các vấn đề liên quan