2012-12-19 16 views
9

Quando si utilizza l'API di trasferimento in background, è necessario eseguire un'iterazione dei trasferimenti di dati correnti per riavviarli nuovamente dopo il riavvio dell'app (ad esempio arresto del sistema). Per ottenere informazioni sullo stato di avanzamento e poter annullare i trasferimenti di dati, è necessario allegarli utilizzando AttachAsync.Come risolvere che AttachAsync di una DownloadOperation non ritorna immediatamente?

Il mio problema è che AttachAsync restituisce solo quando il trasferimento dei dati è terminato. Questo ha senso in alcuni scenari. Ma quando si hanno più trasferimenti di dati, il successivo trasferimento nell'elenco non verrà avviato fino a quando non viene completato il collegamento corrente. La mia soluzione a questo problema è stato quello di gestire il compito che AttachAsync() AsTask() restituisce nel modo classico (non utilizzare attendere ma continuazioni):.

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

E 'sorta di lavori (nel codice attuale aggiungo il download in un ListBox). Il ciclo itera su tutti i download ed esegue StartAsync. Ma i download non sono realmente iniziati tutti allo stesso tempo. Solo uno è in esecuzione alla volta e solo se termina il successivo continua.

Qualche soluzione per questo problema?

risposta

3

L'intero punto di Task consente di avere l'opzione delle operazioni parallele. Se hai await allora stai dicendo al codice di serializzare le operazioni; se non ti aspetti, allora stai dicendo al codice di parallelizzare.

Quello che puoi fare è aggiungere ogni attività di download ad un elenco, dicendo al codice di parallelizzare. Puoi quindi attendere che le attività finiscano, una alla volta.

ne dite qualcosa di simile:

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

Grazie, ma la questione non riguardava le attività. Riguardava il problema che AttachAsync non viene restituito fino al completamento del download. La mia soluzione funziona. La vera risposta alla mia domanda sarebbe che questo comportamento di AttachAsync ci permette di rilevare quando un download è finito. –

+0

@ Jürgen Bayer - Forse non sto capendo dove sia il tuo problema. Quando eseguo il mio codice sopra nel debugger, la riga che esegue 'AttachAsync' restituisce immediatamente. L'unico posto che attende è il ciclo 'while', che dovrebbe attendere: gestisce l'evento di completamento dei download. –

+0

Che AttachAsync restituisce immediatamente è per scopo poiché non lo chiamo con attendi ma utilizzo l'attività restituita per creare continuazioni. Il problema era: se un'app è stata terminata mentre erano attivi più download, cercavo una soluzione per collegare tutti i download quando l'app si riavvia senza attendere ogni AttachAsync. La mia speranza era che i download fossero eseguiti parallelamente come fanno se sono stati avviati più volte utilizzando StartAsync (quando il metodo che richiama StartAsync viene eseguito più volte). Ma questo non succede. Con AtttachAsync viene eseguito un solo download alla volta. –

Problemi correlati