Я использую задачи для выполнения длительных вызовов сервера в моей модели просмотра, и результаты снова упорядочиваются при Dispatcher
использовании TaskScheduler.FromSyncronizationContext()
. Например:
var context = TaskScheduler.FromCurrentSynchronizationContext();
this.Message = "Loading...";
Task task = Task.Factory.StartNew(() => { ... })
.ContinueWith(x => this.Message = "Completed"
, context);
Это нормально работает, когда я запускаю приложение. Но когда я запускаю свои NUnit
тесты, Resharper
я получаю сообщение об ошибке при вызове FromCurrentSynchronizationContext
как:
Текущий SynchronizationContext нельзя использовать в качестве TaskScheduler.
Я предполагаю, что это потому, что тесты выполняются в рабочих потоках. Как я могу убедиться, что тесты выполняются в основном потоке? Любые другие предложения приветствуются.
TaskScheduler.FromCurrentSynchronizationContext()
лямбда-выражение, и выполнение было отложено до другого потока. получение контекста за пределами лямбда решило проблему.Ответы:
Вам необходимо предоставить SynchronizationContext. Вот как я с этим справляюсь:
источник
TestInitializeAttribute
, иначе пройдет только первый тест.Решение Ритча Мелтона не сработало для меня. Это потому, что моя
TestInitialize
функция асинхронная, как и мои тесты, поэтому с каждымawait
токомSynchronizationContext
теряется. Это связано с тем, что, как указывает MSDN,SynchronizationContext
класс «тупой» и просто ставит в очередь всю работу в пуле потоков.Что сработало для меня, на самом деле просто пропустил
FromCurrentSynchronizationContext
вызов, когда нетSynchronizationContext
(то есть, если текущий контекст равен нулю ). Если нет потока пользовательского интерфейса, мне вообще не нужно с ним синхронизироваться.Я нашел это решение более простым, чем альтернативы, в которых:
TaskScheduler
ViewModel (через внедрение зависимостей)SynchronizationContext
и «поддельный» поток пользовательского интерфейса для запуска тестов - для меня больше проблем, чем оно того стоитЯ теряю некоторые нюансы потоковой передачи, но я явно не тестирую, что мои обратные вызовы OnPropertyChanged запускаются в конкретном потоке, поэтому я согласен с этим. Другие ответы с использованием в
new SynchronizationContext()
любом случае не лучше для этой цели.источник
else
случай также потерпит неудачу в приложении службы Windows, в результатеsyncContextScheduler == null
[RequiresThread]
атрибутом.Я объединил несколько решений, чтобы гарантировать работу SynchronizationContext:
Использование:
источник