Страницы

Поиск по вопросам

среда, 27 февраля 2019 г.

Dispatcher не запускает метод в нужном потоке

У меня есть WPF окно, по событию которого вызывается комманда ViewModel. Она в свою очередь вызывает метод из BAL, запускающий дочерний поток(может жить от 10 сек до бесконечности). Данный поток генерирует события по мере выполнения и еще одно событие в самом конце, извещающее о конце работы. Тк события происходят не основном потоке, то ViewModel использует Dispatcher для синхронизации. Если я что-то на проектировал не так, буду рад узнать. Для выполнения кода в нужном потоке я использую следующий код
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(SomeMethod));
Но этот код не вызывает мне нужный метод в обще. Далее я попробовал вызвать следующий код
Dispatcher.CurrentDispatcher.Invoke(new Action(SomeMethod));
В итоге я все равно получил ошибку, тк выполнение не в главном потоке. Тестирования ради я объявил поле _dispatcher и инициализировал его в конструкторе в время работы главного потока. Данный диспетчер мне уже все спокойно вызывал. С чем это связано и как мне быть? Если я вдруг создам ViewModel не в главном потоке, то у меня опять работать ничего не будет.


Ответ

Смотрите.
Dispatcher.CurrentDispatcher возвращает вам диспетчер для данного потока. Поэтому у вас нету альтернативы хранению ссылки на диспетчер.
Затем, VM-объекты обязаны бежать в UI-потоке (иначе вы не сможете биндить к ним View), так что они должны конструироваться тоже в UI-потоке. А значит, вы вполне можете рассчитывать на то, что уж в конструкторе у вас будет правильный Dispatcher.CurrentDispatcher

Почему не работает диспетчер, созданный в фоновом потоке? Диспетчер — это абстракция над циклом сообщений. Если в данном потоке бежит цикл сообщений, то Dispatcher.CurrentDispatcher его вам и возвращает. Если же для данного потока диспетчера нету, создаётся новый и прикрепляется к данному потоку. Но этот диспетчер ещё не запущен! Команда лежит в очереди и дожидается. Если вы запустите диспетчер в фоновом потоке, то все команды, отосланные ему, будут выполнены.
Однако, не пытайтесь сделать это в потоке из пула потоков: для работы диспетчера поток должен быть STA, а потоки из пула — не STA (и это нельзя поменять).
Ну и по-хорошему обычно вам должно хватать диспетчера в UI-потоке.

Комментариев нет:

Отправить комментарий