3

我有一些商业设备,可以通过设备制造商提供的 .Net 库连接到这些设备 - 所以我无法控制库或设备,只有我的代码。

制造商已经设置了他们的系统,因此如果您没有通过他们的库连接到设备,那么它可以正常工作。但是,当您确实连接到他们的库时,有一个隐含的要求,即您以设备运行速度设置的速率为 Windows 消息泵提供服务。这是因为他们的库实现了一个事件系统,您可以订阅该事件系统来跟踪设备的操作,但他们假设您的应用程序代码将基于 WinForms。(但在他们的文档中没有明确说明这一点 - 只是他们的所有 2 个 .Net 示例程序都是基于 WinForms 的。)我已经向他们的技术支持确认,期望您将使用 WinForms 应用程序。

就我而言,我正在编写一个基于 C#、非 WinForms 的应用程序(实际上是一个 Windows 服务,所以我没有 UI 线程),即使我正在连接到设备,我也没有订阅任何事件。结果,我发现我需要引用 WinForms 程序集并以足够快的速度调用 Application.DoEvents() 来服务所有我不订阅的事件。

所以我的问题是:

  1. 在这种情况下,我唯一的选择是调用 Application.DoEvents() 吗?
  2. 还是有更现代的方法来做到这一点?
  3. 以 20 毫秒的速率调用 DoEvents() 的后果是什么?
  4. 不相关,但如果我编写了一个基于 WPF 的应用程序,该程序是否可能为消息泵提供服务?

编辑

我应该补充一点,如果您连接到设备并且不为 windows 消息泵提供服务(即使没有订阅他们的任何事件),那么设备会开始出现不可预测的行为。

编辑 2

此外,我用来连接库的线程也从最初的 Windows 服务线程中删除了大约 2 或 3 代。

4

2 回答 2

6

这很好,DoEvents 的常见警告在这里不适用,因为您没有 UI。没有任何后果,利率是现实的。Application.Run() 也泵送消息循环,但由于调用不返回,您将难以控制线程。是的,WPF 也泵送消息循环,但使用它没有什么意义,因为您没有 UI。

您应该通过调用 SetApartmentState() 来选择 STA 来初始化服务线程。这可确保任何 COM 服务器正常工作。

哦,突然想到一个警告:您确实需要做一些事情来防止线程燃烧 100% 核心。Application.Run() 是自动的,但“游戏循环”中的 DoEvents 不是。我认为您已经这样做了,因为您可以指定 20 毫秒的速率。否则,在服务停止请求事件上调用 WaitHandle.WaitOne(20) 是典型的方法。

于 2010-10-01T13:24:24.607 回答
2

您可以在没有表单的情况下使用消息泵,只需调用Application.Run()带有ApplicationContext或线程上没有参数的版本。

编辑:我会推荐 ApplicaitonContext 版本,以便您可以在您的服务中调用ApplicationContext.ExitThread() 。OnStop()

于 2010-10-01T13:20:56.870 回答