我们雇用了一家公司,将控制某些工业机械的旧VB6 DLL转换为C#。旧的VB6代码具有“暂停”例程,该例程由带有 DoEvents 的 sleep 调用组成,因此在 sleep 时,仍将处理DLL中的计时器和套接字事件。 DoEvents被转换为

System.Windows.Forms.Application.DoEvents();

我不是VB6程序员,但我的理解是VB6实际上是单线程的,因此长时间 sleep 会关闭一切,包括计时器和套接字事件处理。

当代码转换为C#时,暂停例程看起来像这样。 。 。
public static void pauseit_ms(ref int milliseconds)
{
    try
    {
        Sleep(milliseconds / 2);
        System.Windows.Forms.Application.DoEvents();
        Sleep(milliseconds / 2);
    }
    catch (Exception exc)
    {
        LogException("pauseit_ms", exc);
    }
}

在.Net中,计时器和套接字事件在各自的线程中运行(在此转换后的代码中,我的大部分工作都是为了使其具有线程安全性!),因此 DoEvents()向我们购买的东西并不明显。但是MSDN说



因此,是否应该将这些 DoEvents()保留在其他事件中(而不是计时器或套接字回调)?还是它们在.Net/C#上下文中是多余的?

最佳答案

DoEvents创建一个附加的消息循环。这只是一个循环,它读取一条消息,对其进行处理,然后再读取下一条消息,直到得到一条应该停止的消息或没有要处理的消息。调用Application.Run将为您的应用程序创建初始消息循环。从这些消息的处理程序之一中创建其他嵌套的消息循环可能会导致all sorts of problems,因此应避免使用ojit_a,除非您非常熟悉它的功能以及在什么情况下可以正确使用它。

在大多数情况下,您的程序应该只是异步的,而不是创建附加的消息循环。而不是在一段时间内阻塞当前线程,您应该使用Timer之类的东西在一段时间后执行方法,而不会阻塞当前线程。



实际等待计时器时间过去或等待套接字获得响应的过程完全不使用任何线程。没有线程坐在那里 sleep ,而是这些操作本质上是异步的。至于用于执行事件处理程序的线程,将有所不同。一些计时器将使用线程池,一些计时器将使用线程,并且一些计时器是可配置的,并且可以执行任何一种操作。套接字可能只使用线程池线程。

关于c# - C#中的DoEvents()实际做什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27153675/

10-11 08:51