Страницы

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

понедельник, 6 января 2020 г.

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

#c_sharp #wpf #многопоточность


У меня есть WPF окно, по событию которого вызывается комманда ViewModel. Она в свою
очередь вызывает метод из BAL, запускающий дочерний поток(может жить от 10 сек до бесконечности).
Данный поток генерирует события по мере выполнения и еще одно событие в самом конце,
извещающее о конце работы. Тк события происходят не основном потоке, то ViewModel использует
Dispatcher для синхронизации. Если я что-то на проектировал не так, буду рад узнать.
Для выполнения кода в нужном потоке я использую следующий код

Dispatcher.CurrentDispatcher.BeginInvoke(new Action(SomeMethod));


Но этот код не вызывает мне нужный метод в обще. Далее я попробовал вызвать следующий код

Dispatcher.CurrentDispatcher.Invoke(new Action(SomeMethod));


В итоге я все равно получил ошибку, тк выполнение не в главном потоке.
Тестирования ради я объявил поле _dispatcher и инициализировал его в конструкторе
в время работы главного потока. Данный диспетчер мне уже все спокойно вызывал.
С чем это связано и как мне быть? Если я вдруг создам ViewModel не в главном потоке,
то у меня опять работать ничего не будет.
    


Ответы

Ответ 1



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

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

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