Лучший отвечающий
Создание вьюхи WPF в бэкграунде

Вопрос
-
Не знаю, туда или не туда пишу, но быть может кто поможет.
Ситуация следующая.
Проект на WPF.
Есть форма. На ней отнаследованная Canvas.
В Canvas этот надо запихнуть векторную графику.
Графику эту создаю в отдельном классе, её и представляющий (отнаследован класс от DrawingVisual).
При выполнении в одном потоке всё нормально - по нажатию кнопки обновляю класс вьюхи, и его в канву добавляю.
Проблема как обычно - при большом количество векторов вьюха обнавляется долка, интерфейс виснет.
Что ж, пытаюсь в потоке запустить. Пробовал и BackgroundWorker и обычные Thread с делегатами.
Собственно проблема:
во вьюхе есть строчка
DrawingContext dc = RenderOpen(); //класс отнаследован от DrawingView по прежнему.
Так вот, если я создаю класс в потоке формы, но в потоке пытаюсь получить контекст - получаю
System.InvalidOperationException was unhandled
Message="Вызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток."
Если же создаю вьюху в потоке, то не могу её добавить в коллекцию элементов канвы, ибо опять таки потоки разные. Хотя и возвращается она через RunWorkerCompletedEventArgs.Result.
Пробовал даже засовывать вьюху в статик какой-нибудь, и из статика забирать - тот же эффек.
Это какая то особенность DrawingVisual?
В том же приложении нормально использую другие потоки для других операций - всё гладко.- Перемещено Siddharth Chavan 1 октября 2010 г. 19:44 MSDN Forums Consolidation (От:Общая Архитектура)
- Перемещено Abolmasov Dmitry 27 октября 2010 г. 11:12 (От:Разное)
27 июля 2009 г. 19:56
Ответы
-
А если попробовать через Dispatcher сделать обращения к этому объекту?
Program Manager, Microsoft Corporation- Помечено в качестве ответа Dmitry AndreevMicrosoft employee 17 декабря 2009 г. 7:09
6 августа 2009 г. 12:26
Все ответы
-
А если попробовать через Dispatcher сделать обращения к этому объекту?
Program Manager, Microsoft Corporation- Помечено в качестве ответа Dmitry AndreevMicrosoft employee 17 декабря 2009 г. 7:09
6 августа 2009 г. 12:26 -
Тоже столкнулся с этой проблемой, просидел к ряду почти сутки, и пока нашёл только одно решение:Векторную графику, которая рисуется в отдельном потоке, можно отрендерить в изображение:
DrawingVisual drawingVisual = RenderVectorGraphic(); RenderTargetBitmap rtb = new RenderTargetBitmap( (int) Root.RenderSize.Width, (int) Root.RenderSize.Height, 96, 96, PixelFormats.Pbgra32); rtb.Render(drawingVisual); rtb.Freeze();
В окне для отображения используем любой элемент, у которого есть Child (в данном случае Root - у меня это имя Border-а)А потом, через Dispatcher.BeginInvoke передаём rtb (ну или через args у BackgroundWorker-а) и уже там пишем:Image img = new Image(); img.Stretch = Stretch.None; img.Source = rtb; Root.Child = img;
Далеко не идеальный конечно вариант, но зато выходит переложить в background-поток достаточно крупную часть вычислений.Был ещё вариант с импользованием HostVisual. Суть вкратце была в том, что в окне создаются Wrapper-ы, которые хранят HostVisual, владельцами которых являются другие потоки.. Но у меня так не получилось. http://blogs.msdn.com/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx Там есть пример, исходники. Может и поможет.Есть подозрение, что можно попробывать при создании графики не закрывать DrawingContext, и передавать его и drawingVisual в место, в котом всё выводится в интерфейс, а уже в том месте и писать:drawingVisual =someDrawingVisual;drawingContext = someDC;drawingContext.Close();Но этот вариант я не проверял.- Предложено в качестве ответа Alexander Moiseev [Starrow] 23 декабря 2009 г. 10:24
23 декабря 2009 г. 9:35 -
По архитектуре WPF, обращение к методам и свойствам классов, отнаследованных от DispatcherObject (а это почти все классы WPF) возможно только из основного треда программы. Исключение делается для отнаследованных от Freezable, если они нахоятся в "замороженном" (т.е. "только для чтения") состоянии. Это нужно иметь в виду. Обращение к объектам следует производить через Dispatcher.Invoke(...) или Dispatcher.BeginInvoke(...).
11 августа 2010 г. 0:11