2012-08-31 8 views
5

Sto lavorando a un'app WPF e voglio semplicemente modificare il cursore prima e dopo l'esecuzione dell'attività. Ho questo codice:Task ContinueWith() non aggiorna il cursore sul thread UI

this.Cursor = Cursors.Wait; 

Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)).ContinueWith(_ => this.Cursor = Cursors.Arrow); 

Il cursore si trasforma in realtà per il cursore di attesa, ma non torna alla freccia quando il compito è fatto. Se metto un breakpoint nel metodo ContinueWith(), viene colpito. Ma il cursore non cambia in una freccia. Perché?

Questo era il vecchio modo in cui lo stavo provando. Il cursore è tornato a una freccia, ma non voglio Wait() per l'attività.

this.Cursor = Cursors.Wait; 

Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)).Wait(); 

this.Cursor = Cursors.Arrow; 

risposta

10

Il cambiamento del cursore deve essere eseguito sul thread dell'interfaccia utente. È possibile utilizzare il il overload of ContinueWith che prende un programmatore di operazione:

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

Task.Factory 
    .StartNew(() => PerformMigration(legacyTrackerIds)) 
    .ContinueWith(_ => this.Cursor = Cursors.Arrow, uiScheduler); 

Oppure utilizzare il metodo Dispatcher.Invoke:

Task.Factory 
    .StartNew(() => PerformMigration(legacyTrackerIds)) 
    .ContinueWith(_ => { Dispatcher.Invoke(() => { this.Cursor = Cursors.Arrow; }); }); 
+0

Non dovrei ricevere un'eccezione? –

+0

@BobHorn Probabilmente lo sei, ma dal momento che si trova in un thread in background, si sta solo riducendo quel thread, non l'intera applicazione. – Servy

+0

Quando provo il primo suggerimento, ottengo un errore in fase di compilazione: 'Impossibile convertire espressione lambda in tipo 'System.Delegate' perché non è un tipo delegato'. –

2

Penso che è necessario utilizzare il contesto di sincronizzazione corretta:

this.Cursor = Cursors.Wait; 

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext()); 

Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)) 
      .ContinueWith(_ => this.Cursor = Cursors.Arrow, uiScheduler); 
2

Il problema è che la continuazione deve essere eseguita nel thread dell'interfaccia utente. Attualmente viene eseguito in un thread in background.

Aggiungere TaskScheduler.FromCurrentSynchronizationContext() al secondo parametro di ContinueWith per eseguirlo nel thread dell'interfaccia utente.

Problemi correlati