Używam zadań do uruchamiania długotrwałych wywołań serwera w moim ViewModel, a wyniki są kierowane z powrotem przy Dispatcher
użyciu TaskScheduler.FromSyncronizationContext()
. Na przykład:
var context = TaskScheduler.FromCurrentSynchronizationContext();
this.Message = "Loading...";
Task task = Task.Factory.StartNew(() => { ... })
.ContinueWith(x => this.Message = "Completed"
, context);
Działa to dobrze, gdy uruchamiam aplikację. Ale kiedy uruchamiam NUnit
testy Resharper
, otrzymuję komunikat o błędzie w połączeniu z FromCurrentSynchronizationContext
:
Bieżący SynchronizationContext nie może być używany jako TaskScheduler.
Wydaje mi się, że dzieje się tak, ponieważ testy są uruchamiane na wątkach roboczych. Jak mogę upewnić się, że testy są uruchamiane w głównym wątku? Wszelkie inne sugestie są mile widziane.
TaskScheduler.FromCurrentSynchronizationContext()
wewnątrz lambdy i wykonanie zostało odłożone na inny wątek. pobranie kontekstu poza lambdę rozwiązało problem.Odpowiedzi:
Musisz podać SynchronizationContext. Oto jak sobie z tym radzę:
źródło
TestInitializeAttribute
, w przeciwnym razie tylko pierwszy test przechodzi.Rozwiązanie Ritcha Meltona nie działało dla mnie. Dzieje się tak, ponieważ moja
TestInitialize
funkcja jest asynchroniczna, podobnie jak moje testy, więc z każdymawait
prądemSynchronizationContext
jest tracony. Dzieje się tak, ponieważ, jak wskazuje MSDN,SynchronizationContext
klasa jest „głupia” i po prostu kolejkuje całą pracę do puli wątków.To, co mi zadziałało, to po prostu pomijanie
FromCurrentSynchronizationContext
wywołania, gdy nie ma znakuSynchronizationContext
(to znaczy, jeśli bieżący kontekst ma wartość null ). Jeśli nie ma wątku interfejsu użytkownika, w pierwszej kolejności nie muszę się z nim synchronizować.To rozwiązanie okazało się prostsze niż alternatywy, w których:
TaskScheduler
do ViewModel (przez iniekcję zależności)SynchronizationContext
i „fałszywy” wątek interfejsu użytkownika, aby testy działały dalej - dla mnie o wiele więcej kłopotu, niż jest to warteTracę część niuansów wątków, ale nie testuję jawnie, czy moje wywołania zwrotne OnPropertyChanged wyzwalają w określonym wątku, więc nie przeszkadza mi to. Inne odpowiedzi
new SynchronizationContext()
nie są tak naprawdę lepsze dla tego celu.źródło
else
sprawa zakończy się niepowodzeniem również w aplikacji usługi systemu Windows, w wyniku czegosyncContextScheduler == null
[RequiresThread]
atrybutem.Połączyłem wiele rozwiązań, aby mieć gwarancję działania SynchronizationContext:
Stosowanie:
źródło