Ситуация следующая.
Проект на WPF.
Есть форма. На ней отнаследованная Canvas.
В Canvas этот надо запихнуть векторную графику.
Графику эту создаю в отдельном классе, её и представляющий (отнаследован класс от DrawingVisual).
При выполнении в одном потоке всё нормально - по нажатию кнопки обновляю класс вьюхи, и его в канву добавляю.
Проблема как обычно - при большом количество векторов вьюха обнавляется долго, интерфейс виснет.
Что ж, пытаюсь в потоке запустить. Пробовал и BackgroundWorker и обычные Thread с делегатами.
Собственно проблема:
во вьюхе есть строчка
Код |
DrawingContext dc = RenderOpen();
|
//класс отнаследован от DrawingView по прежнему.
Так вот, если я создаю класс в потоке формы, но в потоке пытаюсь получить контекст - получаю
Код |
System.InvalidOperationException was unhandled Message="Вызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток."
|
Если же создаю вьюху в потоке, то не могу её добавить в коллекцию элементов канвы, ибо опять таки потоки разные. Хотя и возвращается она через RunWorkerCompletedEventArgs.Result.
Пробовал даже засовывать вьюху в статик какой-нибудь, и из статика забирать - тот же эффек.
Вот, к примеру, то что сейчас имею:
Это я в саму канву засунул:
Код |
public void AddNewMapView(MifViewParametrs mifViewParametrs) //вход { _backgroundWorker.RunWorkerAsync(mifViewParametrs); }
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { MifViewParametrs mifViewParametrs = (MifViewParametrs) e.Argument; MifViewCreater creater = new MifViewCreater(); e.Result = creater.GetMifView(mifViewParametrs); }
void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { throw new NotImplementedException(); }
void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { AddVisual((Visual)e.Result); }
public void AddVisual(Visual visual) { visuals.Add(visual); base.AddVisualChild(visual); base.AddLogicalChild(visual); }
|
Это собственно в прослойке:
Код |
public MIFView GetMifView(MifViewParametrs parametrs) { MIFView view = new MIFView(parametrs.MIFFile, parametrs.ActualWidth, parametrs.ActualHeight,parametrs.UseBounds, parametrs.LevelNum, null); return view; }
|
Результат возвращается, я visual в 25й строке вижу прекрасно. Сам Exception, судя по стеку возникает где то при отрисовке:
Код |
System.InvalidOperationException was unhandled Message="Вызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток." Source="WindowsBase" StackTrace: в System.Windows.Threading.Dispatcher.VerifyAccess() в System.Windows.Threading.DispatcherObject.VerifyAccess() в System.Windows.DependencyObject.GetValue(DependencyProperty dp) в System.Windows.Media.Pen.get_Thickness() в System.Windows.Media.Pen.GetBasicPenData(MIL_PEN_DATA* pData, Double[]& dashArray) в System.Windows.Media.PathGeometry.GetPathBoundsAsRB(PathGeometryData pathData, Pen pen, Matrix worldMatrix, Double tolerance, ToleranceType type, Boolean skipHollows) в System.Windows.Media.Geometry.GetBoundsInternal(Pen pen, Matrix matrix, Double tolerance, ToleranceType type) в System.Windows.Media.BoundsDrawingContextWalker.DrawGeometry(Brush brush, Pen pen, Geometry geometry) в System.Windows.Media.RenderData.DrawingContextWalk(DrawingContextWalker ctx) в System.Windows.Media.RenderData.GetContentBounds(BoundsDrawingContextWalker ctx) в System.Windows.Media.DrawingVisual.GetContentBounds() в System.Windows.Media.Visual.GetHitTestBounds() в System.Windows.Media.Visual.PrecomputeContent() в System.Windows.Media.DrawingVisual.PrecomputeContent() в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.PrecomputeRecursive(Rect& bboxSubgraph) в System.Windows.Media.Visual.Precompute() в System.Windows.Media.CompositionTarget.System.Windows.Media.ICompositionTarget.Render(Boolean inResize, Channel channel) в System.Windows.Media.MediaContext.Render(ICompositionTarget resizedCompositionTarget) в System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget) в System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(Object resizedCompositionTarget) в System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) в System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) в System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) в System.Windows.Threading.DispatcherOperation.InvokeImpl() в System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) в System.Threading.ExecutionContext.runTryCode(Object userData) в System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) в System.Windows.Threading.DispatcherOperation.Invoke() в System.Windows.Threading.Dispatcher.ProcessQueue() в System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) в MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) в MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) в System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter) в System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) в System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler) в System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) в System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg) в MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) в MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) в System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) в System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) в System.Windows.Threading.Dispatcher.Run() в System.Windows.Application.RunDispatcher(Object ignore) в System.Windows.Application.RunInternal(Window window) в System.Windows.Application.Run(Window window) в System.Windows.Application.Run() в MIFImpoterUI.App.Main() в I:\myprojects\mapviever\GoogleLoader\MIFImpoterUI\obj\Debug\App.g.cs:строка 0 в System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) в System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() в System.Threading.ThreadHelper.ThreadStart_Context(Object state) в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) в System.Threading.ThreadHelper.ThreadStart() InnerException:
|
Это какая то особенность Visual?
В том же приложении нормально использую другие потоки для других операций - всё гладко.
Буду рад любым предложениям по созданию DrawingVisual в отдельном потоке.