use*_*117 8 c# vb6 multithreading
我们聘请了一家公司将一个控制某些工业机械的旧VB6 DLL转换为C#.旧的VB6代码具有"暂停"例程,由睡眠调用和DoEvents组成,因此在休眠时,DLL中的计时器和套接字事件仍将被处理.DoEvents转换为
System.Windows.Forms.Application.DoEvents();
Run Code Online (Sandbox Code Playgroud)
我不是VB6程序员,但我的理解是VB6实际上是单线程的,因此长时间休眠会关闭所有内容,包括计时器和套接字事件处理.
当代码转换为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);
}
}
Run Code Online (Sandbox Code Playgroud)
在.Net中,计时器和套接字事件在它们自己的线程中运行(我在这个转换后的代码中的大多数工作都是试图使它成为线程安全的!)所以DoEvents()买了什么并不明显.但是MSDN说
调用此方法会导致在处理所有等待窗口消息时挂起当前线程.
那么我们应该将这些DoEvents()保留在其他类型的事件(不是定时器或套接字回调)中吗?或者它们在.Net/C#上下文中是多余的?
Ser*_*rvy 10
DoEvents创建一个额外的消息循环.它只是一个循环,它读取消息,处理它,然后读入下一条消息,直到它收到一条消息,它应该停止,或者没有要处理的消息.调用Application.Run为您的应用程序创建初始消息循环.从其中一个处理程序中为这些消息创建其他嵌套消息循环可能会导致各种问题,因此除非您非常熟悉它的作用以及在什么情况下可以正确使用它,否则应该避免它.
在大多数情况下,您的程序应该只是异步,而不是创建一个额外的消息循环.而不是阻止一段时间的当前线程,你应该使用类似一个Timer执行一段时间后一种方法,而不会阻塞当前线程.
在.Net中,计时器和套接字事件在它们自己的线程中运行
实际等待Timer的时间过去,或者套接字得到响应,完全没有使用任何线程.没有线程坐在那里睡觉,而是操作本质上是异步的.至于用于执行事件处理程序的线程,这将有所不同.一些计时器将使用一个线程池,一些是UI线程,一些是可配置的,可以做任何一个.套接字可能只是使用线程池线程.
VB6 DoEvents暂停当前过程的处理(这是可能发生的唯一方法),处理应用程序消息队列中的所有消息(因此事件可能会触发),从而使您的过程可重入.然后它调用Windows API函数Sleep(0).Windows然后做它的消息.最后,您的程序将重新启动.
好的一点是,当你遇到多线程的问题时,你仍然是单线程的,所以简单的代码就像If InProc = True then Exit Function:InProc = True:...:InProc = False:End Function工作一样,因为它无法在中途被抢占.