J'utilise des tâches pour exécuter des appels de serveur de longue durée dans mon ViewModel et les résultats sont rassemblés lors de l' Dispatcher
utilisation TaskScheduler.FromSyncronizationContext()
. Par exemple:
var context = TaskScheduler.FromCurrentSynchronizationContext();
this.Message = "Loading...";
Task task = Task.Factory.StartNew(() => { ... })
.ContinueWith(x => this.Message = "Completed"
, context);
Cela fonctionne bien lorsque j'exécute l'application. Mais quand j'exécute mes NUnit
tests, Resharper
j'obtiens le message d'erreur sur l'appel à FromCurrentSynchronizationContext
comme:
Le SynchronizationContext actuel ne peut pas être utilisé comme un TaskScheduler.
Je suppose que c'est parce que les tests sont exécutés sur des threads de travail. Comment puis-je m'assurer que les tests sont exécutés sur le thread principal? N'importe quelles autres suggestions sont les bienvenues.
TaskScheduler.FromCurrentSynchronizationContext()
intérieur d'un lambda et l'exécution a été reportée à un autre thread. obtenir le contexte en dehors de lambda a résolu le problème.Réponses:
Vous devez fournir un SynchronizationContext. Voici comment je le gère:
la source
TestInitializeAttribute
, sinon seul le premier test réussit.La solution de Ritch Melton n'a pas fonctionné pour moi. C'est parce que ma
TestInitialize
fonction est asynchrone, tout comme mes tests, donc à chaque fois queawait
le courantSynchronizationContext
est perdu. Cela est dû au fait que, comme MSDN le souligne, laSynchronizationContext
classe est «stupide» et met tout simplement en file d'attente tous les travaux dans le pool de threads.Ce qui a fonctionné pour moi, c'est simplement sauter l'
FromCurrentSynchronizationContext
appel quand il n'y a pas deSynchronizationContext
(c'est-à-dire si le contexte actuel est nul ). S'il n'y a pas de thread d'interface utilisateur, je n'ai pas besoin de me synchroniser avec lui en premier lieu.J'ai trouvé cette solution plus simple que les alternatives, qui où:
TaskScheduler
à ViewModel (via l'injection de dépendances)SynchronizationContext
et un "faux" fil d'interface utilisateur pour les tests à exécuter - beaucoup plus de problèmes pour moi que cela en vaut la peineJe perds une partie de la nuance de thread, mais je ne teste pas explicitement que mes rappels OnPropertyChanged se déclenchent sur un thread spécifique, donc je suis d'accord avec cela. Les autres réponses utilisant
new SynchronizationContext()
ne font pas vraiment mieux pour cet objectif de toute façon.la source
else
cas échouera également dans une application de service Windows, ce qui entraînerasyncContextScheduler == null
[RequiresThread]
attribut.J'ai combiné plusieurs solutions pour avoir la garantie de fonctionner SynchronizationContext:
Usage:
la source