【问题标题】:Thread invoke the main window?线程调用主窗口?
【发布时间】:2013-05-07 16:25:21
【问题描述】:

所以基本上我有一个MainWindow,一个类SetupViewModel在一个单独的cs文件中定义,另一个类ImageViewModel在一个单独的cs文件中; 我想知道无论如何我可以从ImageViewModel 调用MainWindow 中的操作。下面列出了更多详细信息:

  • 在 ImageViewModel 中,调用 MainWindow 中的更改如下(遵循MainWindow 中的代码):

    this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new Action(
                        delegate()
                        {
                                ((SetupViewModel)this.DataContext).ViewType = Convert.ToInt32(ViewTypes.ViewType2D);
                        }
                    )
                );
    
  • ViewType 变量在SetupViewModel 中定义如下

    private int _viewType;
        public int ViewType
        {
            get
            {
                return _viewType;
            }
            set
            {
                _viewType = value;
                OnPropertyChanged("ViewType");
            }
        }
    
  • 这是我的做法,但没有成功; ImageViewModel中的调用代码:

    试试 { 动作 SwitchTo2DView = delegate() { ((CaptureSetupViewModel)System.Windows.Application.Current.MainWindow.DataContext).ViewType = Convert.ToInt32(ViewTypes.ViewType2D); };

                System.Windows.Application.Current.MainWindow.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, SwitchTo2DView);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught exception: " + ex.ToString());
            }
    

还有例外:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at CaptureSetupDll.ViewModel.LiveImageViewModel.<StartZStackPreview>b__2c()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   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, Boolean isSingleParameter)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   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 System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method)
   at CaptureSetupDll.ViewModel.LiveImageViewModel.StartZStackPreview()

我是 C# 的外行;知道我怎样才能完成这项工作吗?非常感谢。

【问题讨论】:

  • 什么是 InnerException 及其堆栈跟踪?
  • Visual Studio 打开时显示的异常窗口将提供此信息。您正在做的是从第二个线程调用 MainWindow 的正确方法。
  • 我正在添加添加图片以向您展示我所看到的。
  • @Ramhound:是的,我想我很困惑,所以我在这里寻求帮助。
  • @SLaks:我已经发布了我能看到的内容,有帮助吗?

标签: c# multithreading invoke mainwindow


【解决方案1】:

我敢打赌,你的 DataContext 在被调用时是空的。这意味着它可能被调用得太早了。这可能意味着你应该把你正在做的任何事情都推到 Dispatcher 上。

虽然您可能假设在调用此方法时您的应用程序已完全加载,但这不一定是正确的。要对此进行测试,请在调试期间设置断点并检查 DataContext 是否为空。

如果它为空,您有两个选择。首先,只是返回。根据调用方法的方式,可能会在加载期间调用多次。稍后的调用可能会显示非空上下文。

另一种选择是使用Dispatcher 稍后在加载应用程序后重新调用该方法。

这里有一个小伪代码,看起来有点像 C#,甚至可以编译:

public void CheckTheDataContext()
{
    // is it null?
    if(this.DataContext == null)
    {
        // then drop an Action re-invoking this method later
        // when the application idles out a bit
        Dispatcher.BeginInvoke((Action)(() =>
        {
            CheckTheDataContext();
        }), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
        return;
    }
    DoSomethingElseWithTheContext(DataContext);
}

【讨论】:

  • 这完全有道理。非常感谢威尔 :)
猜你喜欢
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-24
  • 2011-04-24
  • 2013-05-06
  • 2011-06-20
  • 1970-01-01
相关资源
最近更新 更多