【问题标题】:realy long time between invoking dispatcher and execution调用调度程序和执行之间的时间很长
【发布时间】:2010-12-30 12:27:15
【问题描述】:

如果这是一个愚蠢的问题,我提前道歉。我的职业是嵌入式 C 程序员,C# 对我来说相对较新。

我有一个应用程序,它基本上归结为以下内容:一个线程轮询外部接口(如果有人感兴趣,可以使用 profibus),当输入数据发生变化时,会引发一个事件并处理新数据。 由于我需要更新的数据使用数据绑定,因此我调用了调度程序。此设置可正常工作数百万次,但有时在执行委托中的代码之前最多需要 6 秒。由于没有其他线程,我看不出有任何原因。 我使用以下事件处理程序。 Container 是对该类数据绑定的 TabItem 的引用。

public void newSlave_InputChanged(object sender, InputChangedEventArgs e)
    {
        DateTime beforeDisp = DateTime.Now;
        Container.Dispatcher.Invoke(DispatcherPriority.Send, (Action)delegate()
        {
            DateTime afterDisp = DateTime.Now;
            if (afterDisp.Subtract(beforeDisp).TotalSeconds > 1)
            {
                /* Breakpoint here to detect the problem */               
            }
            /* Do the work I need to do */           

        }
    );
    }

轮询外部接口的线程基本上是这样的:

void monitorSlaves()
    {
        while (true)
        {
            if (cardOnline)
            {
                foreach (slave slv in slaves)
                {
                    /* get the data */
                        if (dataChanged)
                        {
                            /* raise event */
                        }
                    }
                }
                Console.WriteLine(string.Format("{0}: Monitor slaves", DateTime.Now));
            }
            Thread.Sleep(200);
        }
    }

我添加了打印以查看在调度程序“挂起”时该线程是否仍在运行。事实证明,事实并非如此。我不知道程序在调用和执行之间的几秒钟内在做什么,因为据我所知没有其他线程在运行。不幸的是,我没有 Visual Studio 2010 终极许可证,所以我不能使用 Intellitrace 来回溯运行的内容。

非常感谢任何输入。

【问题讨论】:

  • 使用性能分析器(例如 Red Gate ANTS Profiler)是否有助于找到 6 秒的去向?还是需要数​​年才能找到百万分之一的发生?
  • 运行这个的机器的规格是什么?是普通 PC 还是精简设备?
  • 幸运的是不需要几年时间。有时应用程序运行一整夜没有任何问题,但大多数情况下它会在启动后一个小时内发生。我会调查分析器,但恐怕我们没有此类软件的任何许可证。我会看看能不能找到一些免费软件替代品。
  • 这是一台普通的PC。我通常做嵌入式,但这是一个模拟我们的嵌入式平台与之交互的东西的工具
  • ANTS Profiler 可免费试用 30 天。应该足以找到问题,如果它真的有帮助,也许钱可以解决下一个类似问题,如果它可以节省您的时间。

标签: c# .net dispatcher


【解决方案1】:

使用 thread.sleep 通常是不好的做法,您可能会冻结整个 UI 线程,从而无法正确调用 Dispatcher。我建议改用 DispatcherTimer

【讨论】:

  • 我假设的代码在后台线程上运行,对吧?
  • 线程休眠与 UI 线程在不同的线程中。该线程不断轮询外部接口。
  • 如果您使用调度程序计时器和 begininvoke 而不是调用,问题是否仍然存在?
  • 我不能使用分派定时器,因为轮询线程位于一个单独的 DLL 中,它对任何 GUI 都一无所知。它基本上只是我使用的接口卡的 DLL 的包装器。我试过 beginInvoke,但不幸的是结果是一样的。
【解决方案2】:

您确定自己看到的是输入吗?

一个可能的问题是接口卡DLL没有及时向您报告输入。

另一个可能的问题是 UI 线程太忙而无法运行您的委托。然而,6 秒是一个很长 的无响应时间。

您可以添加简单的跟踪来确定原因。只需调用Trace.TraceInformation 在发布模式下记录简单的字符串。然后下载DebugView,它可以显示那些跟踪消息。您还可以设置 DebugView 为它们添加时间戳并将它们保存到文件中。

附:巧合的是,我是一名 .NET 开发人员,现在正在研究嵌入式固件。 :)

【讨论】:

    【解决方案3】:

    我打赌延迟是因为垃圾收集器正在收集你创建的一堆小对象。运行 perfmon 并查看所有集合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-23
      • 2021-07-28
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      相关资源
      最近更新 更多