System.InvalidOperationException调用线程无法访问此对象,因为另一个线程拥有它

时间:2012-12-04 17:31:00

标签: wpf multithreading c#-4.0

我有一个繁忙的指示符,我想在我的应用程序进行一些计算时显示。

var uiThread = new Thread(() =>
    {
        autoResetEvent.Set();
        bussyWindowVM.Dispatcher = Dispatcher.CurrentDispatcher;
        Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate
            {
                var busyWindow = new BusyWindow
                {
                    DataContext = bussyWindowVM, 
                    Owner = Application.Current.MainWindow,
                    WindowStartupLocation = WindowStartupLocation.CenterOwner
                };
                busyWindow.Show();
            });

        Dispatcher.Run();
    });
// set single threaded apartment
uiThread.SetApartmentState(ApartmentState.STA);

// mark UI thread as background thread
uiThread.IsBackground = false;

// start the UI thread
uiThread.Start();

// wait until thread exits
autoResetEvent.WaitOne();

但是当我运行应用程序时它会抛出

  

System.InvalidOperationException“{调用线程无法访问   这个对象,因为一个不同的线程拥有它。}“

我无法弄清楚如何解决这个问题。

但是,如果我删除Owner = Application.Current.MainWindow,那么一切正常,但所有者设置不正确,所以我重新调整应用程序的大小,窗口不会成为应用程序的中心。当我最小化应用程序时,它仍然保持最佳状态。

堆栈追踪:

   at System.Windows.Threading.DispatcherObject.VerifyAccess()
   at System.Windows.Application.get_MainWindow()
   at MyProject.MyViewModel.<>c__DisplayClass3.<CreateBusyWindow>b__2() in D:\MyStuff\Dev\Repo\MyProject\ViewModels\MyViewModel.cs:line 2482
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at CivilGeo.GeoHECRAS.ViewModels.GeoHECRASViewModel.<>c__DisplayClass3.<CreateBusyWindow>b__1() in D:\MyStuff\Dev\CivilGeoRepo\GeoHECRAS\CivilGeo.GeoHECRAS\ViewModels\GeoHECRASViewModel.cs:line 2492
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

1 个答案:

答案 0 :(得分:0)

后台线程中的

Dispatcher.CurrentDispatcher为该主题创建一个全新的Dispatcher 此调度程序无法访问原始UI线程中的对象,例如Application.Current.MainWindow

如果要运行单独的UI线程,则无法设置Owner。此外,您不应该致电BeginInvoke()