Events 在VB6中,为什么事件处理在睡眠循环中停止?

Events 在VB6中,为什么事件处理在睡眠循环中停止?,events,vb6,Events,Vb6,我有一个VB6 ActiveX EXE,它有一个OCX控件的事件处理程序。在ActiveX的Terminate函数中,我需要确保在允许Terminate完成之前,所有事件都已完成处理。在Terminate函数中,我在开头添加了以下代码: While EventsInProgressFlags <> 0 DoEvents Sleep(200) WEnd whileeventsinprogressflags 0 多芬特 睡眠(200) 温德 EventsInProgr

我有一个VB6 ActiveX EXE,它有一个OCX控件的事件处理程序。在ActiveX的Terminate函数中,我需要确保在允许Terminate完成之前,所有事件都已完成处理。在Terminate函数中,我在开头添加了以下代码:

While EventsInProgressFlags <> 0
    DoEvents
    Sleep(200)
WEnd
whileeventsinprogressflags 0
多芬特
睡眠(200)
温德
EventsInProgressFlags是一个整数,用于设置正在进行的事件。然而,我观察到的是,当这个循环运行时,正在进行的事件永远不会完成。通过向事件和terminate例程添加许多日志消息,我可以看到,在调用terminate函数时,事件处理正在进行中,但即使调用DoEvents,这些正在进行的事件在terminate函数处于活动状态时也不会执行。如果我强制Terminate函数退出循环,那么事件处理将从它停止的位置继续,但当然会有错误,因为Terminate破坏了事件使用的组件

在我的睡眠循环中是否有一种方法允许正在进行的事件代码完成执行

================更新日期:2018年11月20日===================

经过一些在线调查,我相信我更好地理解了原因,但还没有一个解决方案

阅读后,我了解到VB6是单线程的,所以是的,我的OCX事件处理和终止函数都在同一个线程中。这就是为什么将终止函数置于睡眠状态不起作用的原因。因为它们都在同一个VB6线程中,所以我也将事件处理置于休眠状态。我想知道我的ActiveX终止函数是如何在我的事件处理代码中间调用的。我的理论是,由于我的事件处理在进行系统调用时会调用VB6,因此除了进行系统调用外,它还会调用DoEvents来服务Windows事件队列。这样做是为了使UI更具响应性。调用DoEvents然后处理ActiveX终止调用的传入Windows事件。如果一些VB6大师能在这里证实我的结论,我会很感兴趣

因此,一种可能的解决方案是,在我处理OCX事件时,如果有某种方法禁止系统调用DoEvents。有人知道这样做的方法吗


另一种可能的解决方案是,如果有一种方法可以从Terminate函数返回,那么事件处理可以继续,但在事件处理完成之前,不会从Terminate函数向主机发送响应。这听起来似乎不太合理。

因此,一旦我了解到VB6是单线程的,我就回到调试器中,并确认当Terminate函数执行VB6堆栈时,OCX事件处理会在堆栈上进一步进行,直到Terminate函数返回。显然,我想要完成的事件处理(在终止退出之前)正在同一个线程中运行。Terminate被“VB6调用”,有效地中断了事件处理,这意味着完成事件处理的唯一方法是从Terminate命令返回。但从Terminate返回时,会向(ActiveX EXE的)主机发出一个信号,表示ActiveX对象已终止,而实际上它并未终止。结果是终止函数返回后OCX事件处理出错

我想要的是一种禁止处理ActiveX EXE传入命令的方法。这将在事件处理过程中延迟终止函数的执行。我找不到任何方法来做那件事

因此,我提出了一个不太优雅的解决方案,那就是增加一个全球的加速终端 由终止子例程设置的布尔标志。然后是错误 生成错误#91“对象变量或未设置块变量”的按钮事件例程的处理程序被修改为忽略错误#91,但前提是HasTerminated布尔标志为True。这样做的目的是中止任何导致错误的事件处理,但前提是ActiveX已终止。这是一个可接受的解决方案,因为OCX事件不需要完成,因为组件正在终止。他们只需要不引起错误。下面是我添加到所有事件处理例程中的一个示例错误处理程序

M_SIGN_CAPTURE_FORM_CLEAR_CLICKED_ERR_HANDLER:
40  If HasTerminated And Err.Number = 91 Then
50      Resume 30 ' Resume at Exit Sub
60  End If

70  ErrBox "ERROR #" & Err.Number & " " & FILE__ _
        & ":m_SignCaptureForm_ClearClicked:" & Erl & Err.Description
80  Resume Next
End Sub

我从未遇到过这种情况,也没有对其进行过调查,但我希望发生的情况是,在终止事件触发之前,ocx的事件处理程序已经被解除挂钩。如果是这样,那么在terminate事件中您无法执行任何操作来允许ocx事件运行。最好的做法可能是在所有预期的ocx事件完成之前,不要在主应用程序中释放(取消实例化)ActiveX exe(从而不会导致ocx事件处理程序解除挂钩并触发终止事件)。
DoEvents
调用API的
Sleep(0)
。Sleep函数在指定的时间间隔内暂停当前线程的执行。MSDN.@MarkL你的结论与我的观察不一致。ActiveX EXE的API Terminate命令负责表单的销毁,因此我的睡眠等待循环阻止了对关联表单和ActiveX EXE COM对象的任何销毁。我还知道(从日志消息)在主机发出终止命令时,正在进行的事件已经在执行。主机不在我的控制之下,因此当终止呼叫发生时,我无法更改。我能看到的唯一选项是调用once terminate将其延迟到其他事件完成。但似乎睡眠循环没有释放执行线程以允许已在进行的事件处理完成。我想了解与vB6中处理事件相关的线程。OCX控件触发正在进行的事件,然后生成一些软件事件。我可以从日志中看到OCX硬件事件和