【问题标题】:VB6 polling vs timer event [closed]VB6轮询与计时器事件[关闭]
【发布时间】:2020-09-10 21:27:03
【问题描述】:

我的应用程序的外部进程每个都轮询一个布尔值以查看是否有工作要做。我现在想在 Timer 事件中检查该变量以减少“未响应”消息。

必须将 Timer 对象放在表单上,​​这似乎会造成一些限制。

使用Me.Show (vbModal) 从表单启动事件效果很好。只是我不想实际显示该表格,我只想使用计时器。尝试使用 Me.Hide 隐藏表单然后失去我需要的模态行为,所以这不是一个好的解决方法。

我尝试从一个类启动事件,但它表现出与 Me.Hide 相同的不良行为:处理返回给调用者,而不是停留在等待工作的计时器事件子中。

有什么方法可以实现基于Timer 的事件,不需要显示表单并且不会立即返回给调用者? 外部进程没有屏幕 IO,也没有想要的。

【问题讨论】:

  • 您似乎不了解阻塞调用和异步调用协议和约定之间的区别和上下文。如果您不阻止调用者(例如,通过模态表单调用),那么执行当然会返回给调用者。实际上,这就是目标。由于您不想显示模态表单,因此您需要重新设计调用者代码,以便它期望接收回执行,但它会暂停执行,直到异步任务(通过计时器运行)完成。 Etienne 的回答和链接为如何在 VB6 中做到这一点提供了指导。
  • 是的,我想这是我的期望偏离的问题。最初我希望有一种简单的方法可以使表单隐藏和模态。在启动工作循环(线程?)并返回给调用者之后必须处理该过程似乎很奇怪。所以现在我们有了(我猜是启动了一个线程来完成这项工作),但我仍然需要处理 ret。我想实际执行工作的“线程”占用与子进程(刚刚返回的)相同的内存空间,所以最好让他提供 DoEvents 供工作“线程”使用。谢谢你的评论。 -鲍勃
  • 不久前,我下载并研究了由著名的 Karl E. Peterson 创建的演示,ccrpTmr6.zip。在计时器事件处理的上下文中,它很好地显示了阻塞与非阻塞的差异。顺便说一句,我认为他可能是你们,你们也可能是他。因此,如果我从 sub Main() 开始演示并将 Me.Show 放在 Form_Load 子中,则事件处理似乎在从 Form_Load 返回之后开始。但是,如果我将 Me.Show(vbModal) 放在 Form_Load 中,则处理从那里开始并且不会返回给调用者。这是我想效仿的“不返回调用者”行为。 -鲍勃

标签: timer vb6 polling


【解决方案1】:

您可以研究使用 Windows API 中的 SetTimer 函数。在 Module 和用户 TimerStart 中添加以下代码,间隔以毫秒为单位:

Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long

Public Function TimerStart(ByVal p_lngInterval As Long) As Long
    
    ' Start timer
    TimerStart = SetTimer(0, 0, p_lngInterval, AddressOf TimerCallBack)

End Function

Public Sub TimerCallBack(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTime As Long)
    
    ' Handle your polling here

End Sub

您不需要表单,所以这应该适合您的需要。

您还可以将 Windows API 中的Sleep 与 Timer 结合使用,以保持您的 EXE 运行:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Public Sub Main()

    TimerStart 2000
    
    Do While True
        DoEvents
        Sleep 1000
    Loop
    
End Sub

有关详细信息,请参阅这些其他答案:

【讨论】:

  • 谢谢,艾蒂安。这比我迄今为止尝试过的任何东西都要好!但由于某种原因,它会从 TimerCallBack 中弹出。奇怪的是,它是在成功完成 3 到 5 个工作任务后才这样做的。我希望我知道是什么让它返回给调用者。我将间隔设置为 10。任何想法将不胜感激。顺便说一句,感谢您的快速回复。 -鲍勃
  • TimerCallBack 代码完成后会退出,是的。也许您甚至不需要计时器,您只想继续寻找任务对吗?在这种情况下,在任务之间建立一个循环的方法可能会更好。也许你可以用你的代码和这个新问题发布一个新问题,其他人可能比我有更多的经验。
  • “也许你甚至不需要计时器” 是的,我正在解决这个问题。在返回给调用者之后,我添加了您的 .DoEvents Sleep 1000 想法并学到了一些有趣的东西。增加睡眠时间会减慢工作进程。反之亦然。由于这个睡眠循环不是寻找工作、工作循环的一部分,我推测工作循环所依赖的正是睡眠循环中的这些 DoEvents。与您的观点相呼应,轮询可以使用相同的技术减少 CPU 使用率......并且代码更少。凉爽的。再次感谢。
猜你喜欢
  • 1970-01-01
  • 2012-03-12
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多