【问题标题】:C# Events firing on wrong threadC# 事件在错误的线程上触发
【发布时间】:2011-02-23 19:53:25
【问题描述】:

全部

我有一个允许用户与多个串行设备通信的应用程序。 管理器类用于启动应用程序,它为每个串行设备创建一个新线程。在这个线程中,串行设备被创建,线程和串行设备对象被存储在管理器类中,以供以后需要时使用。

串行设备类然后在它自己的新线程上创建一个 com 端口类,用于连接到 com 端口并发送/接收数据。当接收到数据时,串行设备类会触发一个事件,该类又会向管理器类触发一个事件,管理器类又会向 UI 触发一个事件,以提醒用户新数据已到达。

我的问题是,当 com 端口类触发它的事件以通知串口类时,串口类接收到该事件并在 com 端口线程下继续处理。同样,如果用户将任何信息发送到 com 端口,它都会在 UI 线程下运行。

我稍后会添加代码作为编辑,但现在,如果有人能发现任何明显的东西,我会非常感激。

我尝试在串行设备类中接收事件,然后调用一个方法来查看它是否可以在正确的线程下运行,但这并不好。

我知道串行设备线程正在运行,因为我在创建它的 com 端口类后在类中运行 Application.Run。

我没有使用任何后台工作线程,因为这些线程在应用程序的整个生命周期中都存在,而且我知道后台工作线程旨在用于短期运行计算。

非常感谢

编辑:

忘了说,这是 .NET 2.0 中的 Winforms 应用,所以没有可用的 Dispatcher

编辑: 好的,看起来信息正在 DataReceived 线程中传递(我认为它也不是 com 端口线程)。 我还尝试将 BackgroundWorker 用于串行设备类,但这也没有任何区别。 帮忙?

【问题讨论】:

  • 你在内部使用System.IO.Ports.SerialPort类吗?
  • 很不清楚。你在使用 SerialPort.DataReceived 事件吗?那么是的,您在线程池线程上接收数据。您最终将不得不使用 Control.BeginInvoke() 来更新 UI。
  • 是的,它是一个 winform 应用程序。接收事件不是问题。我收到所有通知,只是在错误的线程上。我想要做的是让串行设备类在它自己的线程上处理通知,而不是在 com 端口或 UI 线程上。是的,它正在使用 DataReceived 事件。
  • 我的问题是,如果 UI 将更新发送到管理器,然后发送到串行设备类,然后发送到 com 端口类,我不希望它们都发生在UI线程,反之亦然。否则事情会被搁置

标签: c# multithreading .net-2.0 serial-port


【解决方案1】:

.NET 2.0 具有 SynchronizationContext。这有点麻烦(您必须将上下文从 UI 线程传递给其他线程),但它应该可以解决问题。

更多信息在这里:http://msdn.microsoft.com/en-us/magazine/gg598924.aspx

【讨论】:

  • 嗨,马克,感谢您回复我。这看起来不错,我试图做的是在串行设备类的构造函数中创建一个 SynchronizationContext 对象,但这似乎总是为空?我用SynchronizationContext obj = SynchronizationContext.Current;。然后,我尝试在 serialdevice 类的初始化期间在管理器类中创建它,但它再次为空。
  • 如果我创建了一个新的 SynchronizationContext,那么它仍然没有显示正确的线程名称...
  • 只有 UI 线程会有 SynchronizationContext;您必须将其传递给您以一种或另一种方式创建的线程。这里有更多信息和示例:daveonsoftware.blogspot.com/2007/11/…
  • 在这种情况下,我如何将一个非 UI 线程编组到另一个线程上?调用似乎应该是前进的方向,但它没有任何区别。
  • 哦...转到另一个 非 UI 线程。嗯。我想知道您是否可以让这些线程创建自己的 SynchronizationContexts;这意味着您将不得不解决消息队列之类的事情,例如该线程有一个List<Action>,所有操作都进入并在循环中运行。我不知道是否有一个简单的答案,但最终我认为你将不得不将你的线程变成它自己的美化消息泵。
【解决方案2】:

听起来好像您需要创建一种消息传递机制来将消息从 UI 线程发送到正确的端口线程。队列可能会起作用。让 UI 线程在队列上发布消息,并让端口线程处理这些消息。

从端口线程切换到 UI 线程可以使用 Dispatcher.CurrentDispatcher 完成

这是你要找的吗?

编辑我假设是一个 WinForms 应用程序

【讨论】:

  • ... 还建议使用 System.Windows.Threading.Dispatcher 类。
  • 相信 OP 声明这是一个 .NET 2.0 应用程序,我认为 Dispatcher 在该版本中不可用。至于消息队列实现的建议,我完全同意这个想法。大约 18 个月前参与了类似应用程序的设计,有类似的问题,消息队列很好地解决了这个问题。队列可以独立于 UI 线程而存在,并且 UI 可以根据需要与队列对话,并且应该减轻(或至少大大简化)线程切换问题。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多