C#中的DoEvents()实际上做了什么?

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

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

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

当代码转换为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为您的应用Application.Run创建初始消息循环。 从其中一个处理程序中为这些消息创建其他嵌套消息循环可能会导致各种问题 ,因此应该避免这种情况,除非您非常熟悉它的作用以及在什么情况下可以正确使用它。

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

在.Net中,计时器和套接字事件在它们自己的线程中运行

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

VB6 DoEvents暂停当前过程的处理(这是可能发生的唯一方式),处理应用程序消息队列中的所有消息(因此事件可能会触发),从而使您的过程可重入。 然后它调用Windows API函数Sleep(0)。 Windows然后做它的消息。 最后,您的程序将重新启动。

好的是,当你遇到multithreading的问题时,你仍然是单线程的,如此简单的代码如If InProc = True then Exit Function:InProc = True:...:InProc = False:End Function将尽可能正常工作中途被抢先一半。

通常,您不想使用Application.DoEvents() 。 如何使用它的一个不好的做法示例是确保在继续在同一个线程上执行长时间运行之前光标更改为等待光标(该操作应该在单独的线程上运行)。

  Cursor.Current = Cursors.WaitCursor; //Makes sure this change takes effect instead of being blocked by the next line. //NOT SUPER RELIABLE Application.DoEvents(); //Do long work here Cursor.Current = Cursors.Default; 

在您的特定情况下,看起来他们正试图将其用作黑客来伪造UI比实际更具响应性。

你应该在循环中使用它:

 await System.Windows.Threading.Dispatcher.Yield() 

创建一个等待对象,该对象异步地将控制权交还给当前的调度程序,并为调度程序提供处理其他事件的机会。

它更好,实际上为您创建了延迟的UI加载。

*Processes all Windows messages currently in the message queue.*

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents%28v=vs.110%29.aspx

它允许Window Forms处理从Window Message Pump等待它的任何消息。 因此,所有代码都会等待一半的时间,然后处理消息并再次等待。