我有一些商业设备可以连接到设备制造商提供的.Net库 - 所以我无法控制库或设备,只能控制我的代码。
制造商已将其系统设置为如果您未通过其库连接到设备,那么它可以正常工作。但是,当您连接其库时,隐含要求您以设备运行速度设置的速率为Windows消息泵提供服务。这是因为他们的库实现了一个事件系统,您可以订阅它来跟踪设备的操作,但他们认为您的应用程序代码将基于WinForms。 (但是在他们的文档中没有明确说明这一点 - 只是他们的.Net示例程序中的所有两个都是基于WinForms的。)我已经向他们的技术支持证实,期望您将使用WinForms应用程序。
在我的情况下,我正在编写一个C#,非基于WinForms的应用程序(实际上是一个Windows服务,所以我没有UI线程),即使我连接到设备,我也没有订阅任何事件。结果我发现我需要引用WinForms程序集并以足够快的速率调用Application.DoEvents()来为我未订阅的所有事件提供服务。
所以我的问题是这些:
修改
我应该补充一点,如果您连接到设备并且不为Windows消息泵提供服务(即使没有订阅他们的任何事件),那么设备开始出现不可预测的行为。
修改2
我用来连接到库的线程也是从初始的Windows服务线程中删除了大约2代或3代。
答案 0 :(得分:6)
这很好,DoEvents的常见警告不适用于此处,因为您没有UI。没有任何后果,速度是现实的。 Application.Run()也会对消息循环进行抽取,但由于调用没有返回,因此您将更难控制线程。是的,WPF也支持消息循环,但由于你没有用户界面,因此没有什么意义。
您应该通过调用SetApartmentState()来选择STA来初始化服务线程。这可确保任何COM服务器正常工作。
哦,有一点需要注意:你需要做些什么来防止线程烧掉100%核心。它是自动使用Application.Run()但不是'游戏循环'中的DoEvents。我想你已经做了,因为你可以指定20毫秒的速率。否则,在服务停止请求事件上调用WaitHandle.WaitOne(20)是典型的方法。
答案 1 :(得分:2)
您可以拥有一个没有表单的消息泵,只需调用Application.Run()
的版本,该版本在一个帖子上占用ApplicationContext或no parameters。
编辑:我会推荐ApplicaitonContext版本,以便您可以在服务的OnStop()
中致电ApplicationContext.ExitThread()。