【问题标题】:this.dispatcher.invoke() does not work for multithreading?this.dispatcher.invoke() 不适用于多线程?
【发布时间】:2013-02-22 14:59:41
【问题描述】:

我再次遇到此错误:调用线程无法访问此对象,因为另一个线程拥有它。

这是我的代码:

 public void InitiateSignalAnalysisPlot()
        {
            if (_nActiveChannel > 0)    // timeDomainPlotter init
            {
                _dataX = new List<double[]>();
                _dataY = new List<double[]>();

                _dataX3 = new List<List<double[]>>();
                _dataY3 = new List<List<double[]>>();

                double[] dataXOneCh = new double[1];
                double[] dataYOneCh = new double[1];

                dataXOneCh[0] = 0;
                dataYOneCh[0] = 0;

                CirclePointMarker pm = new CirclePointMarker { Size = 5, Fill = Brushes.Transparent };

                for (int i = 0; i < _nActiveChannel; i++)
                {
                    if (_nActiveStatsOneChannel > 0)
                    {
                        for (int j = 0; j < _nActiveStatsOneChannel; j++)
                        {
                            _dataX.Add(dataXOneCh);    // data x-y mapping init
                            _dataY.Add(dataYOneCh);

                            EnumerableDataSource<double> xOneCh = new EnumerableDataSource<double>(dataXOneCh);
                            EnumerableDataSource<double> yOneCh = new EnumerableDataSource<double>(dataYOneCh);

                            xOneCh.SetXMapping(xVal => xVal);
                            yOneCh.SetXMapping(yVal => yVal);

                            CompositeDataSource dsOneCh = new CompositeDataSource(xOneCh, yOneCh);

                            Action InitiatePlotter = delegate()
                            {
                                LineAndMarker<MarkerPointsGraph> lam = timeDomainPlotter.AddLineGraph(dsOneCh,
                                                                                       new Pen(pm.Fill, 2),
                                                                                       pm,
                                                                                       new PenDescription("C" + Convert.ToString(i) + "S" + Convert.ToString(j)));
                            };

                            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, InitiatePlotter);
                        }

                        _dataX3.Add(_dataX);
                        _dataY3.Add(_dataY);
                    }
                }

                timeDomainPlotter.FitToView();
            }
            else
            {
                return;
            }
        }

错误发生在"this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, InitiatePlotter);" 这是由主窗口线程调用的 WPF 窗口后面的一段代码。我很困惑我使用 dispatcher.invoke() 来取消这个多线程冲突,为什么我仍然收到这个错误?如果我将这段代码放入被调用窗口的构造函数中,它可以工作,但我只是不想那样做。我可以做些什么改变来避免这个错误?谢谢。

更多可能有帮助的信息: timeDomainPlotter 在 wpf 窗口 B 中,在窗口 A 中启动 (WindowB _windowB = new WindowB(); );上面的代码 InitiateSignalAnalysisPlot() 也在窗口 B 中,但在窗口 A 中调用了 InitiateSignalAnalysisPlot(),类似于 _windowB,InitiateSignalAnalysisPlot();

如果我不 Dispatcher.Invoke() 它,也会有一个异常,即The calling thread must be STA, because many UI components require this.,发生在

LineAndMarker<MarkerPointsGraph> lam = timeDomainPlotter.AddLineGraph(dsOneCh,
                                                                                       new Pen(pm.Fill, 2),
                                                                                       pm,
                                                                                       new PenDescription("C" + Convert.ToString(i) + "S" + Convert.ToString(j)));

【问题讨论】:

  • 也许检查您是否需要使用 Dispatcher.CheckAccess() 调用它
  • 当我输入 Dispatcher 时,没有自动弹出 CheckAccess() 方法.....
  • 它就在那里;出于某种原因,Microsoft 决定将 Dispatcher.CheckAccess() 和 Dispatcher.VerifyAccess() 设置为不显示在智能感知(属性/方法/等的弹出列表)中。如果您继续输入它,它将编译。也就是说,这里的 CheckAccess() 实际上不会告诉你任何你不知道的事情。
  • 是的,Dispatcher.CheckAccess() 返回 false。这是什么意思?
  • 这意味着当您调用 Dispatcher.CheckAccess() 时,该调用在“错误”线程上运行,即不是 Dispatcher 正在管理的线程。但是你已经知道了,因为这就是你得到例外的原因。 CheckAccess() 方法只是一种提前检查的方法,而不是找出异常发生的时间。这不是新信息,对您没有任何帮助。

标签: c# wpf multithreading


【解决方案1】:

您在哪里创建 timeDomainPlotter?

在不同线程上创建的控件有不同的 Dispatcher。我的猜测是您遇到此错误是因为您正在通过“this.Dispatcher”调用您的委托,但是您在该委托中触摸的控件是在不同的线程上创建的,因此具有不同的调度程序'这个'。

如果它在不同的线程上,也许您可​​以为创建设置一个委托并通过 this.Dispatcher 调用该委托,然后控件将在您稍后尝试访问它的同一线程上创建。

【讨论】:

  • timeDomainPlotter 是我从工具箱拖到 wpf 窗口窗体上的控件,该窗体由主窗口调用。我发布的那段代码在 wpf 表单后面的 C# 代码中,timeDomainPlotter 就在其中。
  • 稍微简化一下:timeDomainPlotter是wpf表单B上的一个控制工具。表单B是在表单A中发起(声明)的,而我帖子上面这段代码是表单B,但是函数 (InitiateSignalAnalysisPlot()) 以 A 形式调用。
  • 只是澄清一些事情。你有你的 WPF 主窗口,我们称之为窗口 A;该窗口打开另一个 WPF 窗口,我们将其称为窗口 B; timeDomainPlotter 控件在窗口 B 中;你给我们的 InitiateSignalAnalysisPlot() 方法在窗口 B 的代码隐藏中?如果一切都是正确的,我不确定问题出在哪里......
  • 是的,这是正确的,但是 InitiateSignalAnalysisPlot() 在窗口 A 中被调用。类似于 _windowB.InitiateSignalAnalysisPlot();其中 _windowB 在窗口 A 中声明
猜你喜欢
  • 2021-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2016-05-29
  • 2014-11-12
相关资源
最近更新 更多