Estoy usando Tasks para ejecutar llamadas de servidor de larga duración en mi ViewModel y los resultados se calculan de nuevo al Dispatcher
usar TaskScheduler.FromSyncronizationContext()
. Por ejemplo:
var context = TaskScheduler.FromCurrentSynchronizationContext();
this.Message = "Loading...";
Task task = Task.Factory.StartNew(() => { ... })
.ContinueWith(x => this.Message = "Completed"
, context);
Esto funciona bien cuando ejecuto la aplicación. Pero cuando ejecuto mis NUnit
pruebas Resharper
, aparece el mensaje de error en la llamada a FromCurrentSynchronizationContext
:
El SynchronizationContext actual no se puede utilizar como TaskScheduler.
Supongo que esto se debe a que las pruebas se ejecutan en subprocesos de trabajo. ¿Cómo puedo asegurarme de que las pruebas se ejecuten en el hilo principal? Cualquier otra sugerencia es bienvenida.
TaskScheduler.FromCurrentSynchronizationContext()
dentro de una lambda y la ejecución se aplazó a otro hilo. obtener el contexto fuera de lambda solucionó el problema.Respuestas:
Debe proporcionar un SynchronizationContext. Así es como lo manejo:
fuente
TestInitializeAttribute
, de lo contrario, solo pasa la primera prueba.La solución de Ritch Melton no funcionó para mí. Esto se debe a que mi
TestInitialize
función es asíncrona, al igual que mis pruebas, por lo que con cadaawait
unaSynchronizationContext
se pierde la corriente . Esto se debe a que, como señala MSDN, laSynchronizationContext
clase es "tonta" y solo pone en cola todo el trabajo en el grupo de subprocesos.Lo que funcionó para mí es en realidad omitir la
FromCurrentSynchronizationContext
llamada cuando no hay unSynchronizationContext
(es decir, si el contexto actual es nulo ). Si no hay un hilo de IU, no necesito sincronizarme con él en primer lugar.Encontré esta solución más sencilla que las alternativas, que donde:
TaskScheduler
a al ViewModel (a través de la inyección de dependencia)SynchronizationContext
y un subproceso de interfaz de usuario "falso" para que se ejecuten las pruebas; muchos más problemas para mí de los que vale la penaPierdo algunos de los matices del subproceso, pero no estoy probando explícitamente que mis devoluciones de llamada OnPropertyChanged se activen en un subproceso específico, así que estoy de acuerdo con eso. De
new SynchronizationContext()
todos modos, las otras respuestas que usan realmente no funcionan mejor para ese objetivo.fuente
else
caso también fallará en una aplicación de servicio de Windows, lo que resultarásyncContextScheduler == null
[RequiresThread]
atributo.He combinado varias soluciones para tener garantía de funcionamiento SynchronizationContext:
Uso:
fuente