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()
4

1 回答 1

1

Dispatcher.CurrentDispatcherDispatcher在您的后台线程中为该线程创建一个全新的。
此调度程序无法从原始 UI 线程访问对象,例如Application.Current.MainWindow.

如果你想运行一个单独的 UI 线程,你将无法设置Owner. 另外,您不应该调用BeginInvoke().

于 2012-12-04T17:34:03.620 回答