2012-08-31 14 views
5

Pracuję nad aplikacją WPF i po prostu chcę zmienić kursor przed i po uruchomieniu zadania. Mam ten kod:Zadanie ContinueWith() Nie aktualizowanie kursora przy użyciu wątku interfejsu użytkownika

this.Cursor = Cursors.Wait; 

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

Kursor rzeczywiście zmienia się na kursor oczekiwania, ale nie zmienia się z powrotem do strzałki po wykonaniu zadania. Jeśli wstawię punkt przerwania w metodzie ContinueWith(), zostanie on trafiony. Ale kursor nie zmienia się z powrotem w strzałkę. Czemu?

To był stary sposób, w jaki próbowałem. Kursor zmienił się z powrotem na strzałkę, ale nie chcę czekać() dla zadania.

this.Cursor = Cursors.Wait; 

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

this.Cursor = Cursors.Arrow; 

Odpowiedz

10

Zmiana kursora musi być wykonana na wątku interfejsu użytkownika. Można też użyć do overload of ContinueWith że trwa harmonogram zadań:

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 

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

Albo użyć metody Dispatcher.Invoke:

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

Czy nie powinienem otrzymać wyjątku? –

+0

@BobHorn Jesteś bardzo prawdopodobne, ale ponieważ jest w wątku tła, to tylko wątku, a nie całej aplikacji. – Servy

+0

Kiedy próbuję pierwszej sugestii, pojawia się błąd podczas kompilacji: 'Nie można przekonwertować wyrażenia lambda na typ 'System.Delegate', ponieważ nie jest to typ delegata'. –

2

Myślę, że trzeba użyć prawidłowego kontekstu synchronizacji:

this.Cursor = Cursors.Wait; 

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext()); 

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

Problem polega na tym, że kontynuacja musi przebiegać w wątku interfejsu użytkownika. Obecnie trwa to w wątku tła.

Dodaj TaskScheduler.FromCurrentSynchronizationContext() do drugiego parametru ContinueWith, aby uruchomić go w wątku interfejsu użytkownika.

Powiązane problemy