Холст WPF:Children.Add() висит в фоновом потоке?
-
03-07-2019 - |
Вопрос
...или...
«Какое зло в глубинах WPF я пробудил?»
Я создаю Canvas в фоновом потоке и преобразую его в растровое изображение.У меня это работает в производственном коде уже больше года без проблем.Я делаю следующее:
- создать объект Canvas
- создать новый объект NameScope
- назначьте этот NameScope Canvas
- рисую на холсте все, что захочу
- вызов Canvas.Measure() с размером Canvas
- вызов Canvas.Arrage() с доступным прямоугольником Canvas
- вызвать холст.UpdateLayout()
- визуализировать холст
На этапе рисования я всегда просто вызывал Canvas.Children.Add(), чтобы поместить UIElements на Canvas.Это всегда работало.
Теперь по какой-то необъяснимой причине в одном конкретном случае в приложении, над которым я работаю, вызов Canvas.Children.Add() зависает на неопределенный срок, блокируя мой фоновый поток.Я не могу вспомнить, что я делаю по-другому между кодом, который работает больше года, и этим конкретным случаем.
Может ли кто-нибудь предложить возможные причины, по которым вызов Canvas.Children.Add() зависает вот так?
Редактировать:Фоновым потоком является поток STA (модель обработки фонового потока была введена, потому что я не мог обрабатывать изображения с помощью WPF в потоке MTA), поэтому модель подразделения потоков не должна быть виновником.
Редактировать №2:Хотя я понимаю, почему люди предлагают мне попробовать Dispatcher.BeginInvoke() из моего фонового потока, мне не нравится этот вариант по двум причинам:
- Я хочу, чтобы моя фоновая обработка потока была синхронной в этом потоке.В моем фоновом потоке есть очередь, в которую другие потоки отправляют задания изображений, а мой фоновый поток обрабатывает каждое задание по мере его поступления.Использование Dispatcher.BeginInvoke() добавляет еще один уровень сложности, которого я бы предпочел избегать.
- Я ни разу нужно до настоящего времени.Выполнение этой фоновой обработки синхронно в моем фоновом потоке просто работал.Я пытаюсь определить, что может быть особенного в этом странном крайнем случае, из-за которого этот код не работает.Если я не смогу заставить его работать, мне придется переписать этот код обработки без WPF, чего я бы предпочел избежать.
Решение
Какую модель квартиры вы используете в качестве фоновой темы?
Я считаю, что WPF должен работать в потоке STA.Когда вы создадите фоновый поток, попробуйте настроить его для STA.
Обновлять:
Если проблема не в потоке STA, я бы попробовал разбить ваш рисунок холста на куски.В основном, если вы делаете:
Диспетчер.BeginInvoke(...)
из вашего потока предоставленный делегат помещается в конец очереди диспетчера, позволяя выполнять другие задачи в очереди.
Обновление 2:
Вы также можете попробовать выполнить отладку исходного кода объекта Canvas, используя справочные источники платформы .NET.Вы можете включить это, включив «включить пошаговое изменение исходного кода .net framework» в параметрах отладки в разделе «Инструменты» -> «Параметры».
Другие советы
Попробуйте вызвать Dispatcher.Run() в фоновом потоке.