代码之家  ›  专栏  ›  技术社区  ›  Peter M

application.doEvents()是我唯一的选择吗(在本例中)?

  •  3
  • Peter M  · 技术社区  · 14 年前

    我有一些商业设备可以连接到设备制造商提供的.NET库,所以我对库或设备没有控制权,只有我的代码。

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

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

    所以我的问题是:

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

    编辑

    我应该补充一点,如果你连接到设备,不服务Windows消息泵(即使没有订阅任何事件),那么设备就会开始不可预知地下降。

    编辑2

    另外,我用来连接库的线程大约是从最初的Windows服务线程中删除的2到3代。

    2 回复  |  直到 14 年前
        1
  •  6
  •   Hans Passant    14 年前

    这很好,通常对doEvents的警告在这里不适用,因为您没有UI。没有任何影响,这个比率是现实的。application.run()也会泵送消息循环,但由于调用没有返回,因此控制线程会比较困难。是的,WPF也启动了消息循环,但是使用它没有什么意义,因为您没有UI。

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

    哦,有一点需要提醒的是:你确实需要做一些事情来防止线燃烧100%的核心。它在application.run()中是自动的,但在“游戏循环”中不使用doEvents。我想你已经这样做了,因为你可以指定一个20毫秒的速率。否则,在服务停止请求事件上调用waithandle.waitone(20)是典型的方法。

        2
  •  2
  •   Scott Chamberlain    14 年前

    你可以在没有表单的情况下发送消息,只需调用 Application.Run() 这需要 ApplicationContext no parameters 在一根线上。

    编辑:我建议您使用applicaitoncontext版本,这样您就可以调用 ApplicationContext.ExitThread() OnStop() 你的服务。