【问题标题】:Why do I need WaitFor'/MsgBox to prevent crashing in VB6 exe that gets data from a C++ DLL为什么我需要 WaitFor'/MsgBox 来防止从 C++ DLL 获取数据的 VB6 exe 崩溃
【发布时间】:2014-03-20 13:31:53
【问题描述】:

我是一般的编程新手,所以请多多包涵。

我正在使用的这个 VB6 程序(我是新来的)使用一个较旧但更新的 Borland C++ DLL(我也在更新)从中获取部件列表。

在 VB6 IDE 的调试模式下一切正常,但是当我创建一个实际的可执行文件并尝试它时,它崩溃了。对此的“修复”在我到达这里之前几年就已经实现了,他们添加了一堆 WaitFor 函数调用来“减慢 VB6 的速度,以便它可以在继续之前完成从 DLL 的读取。”

奇怪的是,我正在更新 VB6 代码,方法是为特定部分放置一些硬编码的 if-checks 并将其放入 DLL,因为它们之前无法更新 Borland C++ DLL。副作用当然是 VB6 代码运行得更快了。

我已将问题范围缩小到时间。有一个部分,如果我只添加一个简单的 MsgBox,它不会崩溃,但 WaitFor,即使设置为 100000... 也不起作用。

所以我的问题是,我是否可以在没有完成从 DLL 读取的情况下阻止 VB6 代码继续运行,而无需任意添加 WaitFors 等。这似乎是一种糟糕的做法,我将在这家公司待一段时间,不要不想继续这种趋势。

谢谢!


更新:

代替 MsgBox 这样做似乎也能正常工作:

Dim x as Long
Dim y as Long
For x= 1 to 500
    y = y + 1
Next

只需添加废话即可解决问题。


WaitFor 函数:

On Error Resume Next
Static dLastDoevents  As Double
Dim SleepyTime        As Integer:   SleepyTime = 20     'set "Sleep peroid" in milliseconds (this is also the resolution of the doevents rate)
Dim DoEventsRate      As Integer:   DoEventsRate = 200     'set "DoEvents rate" in milliseconds
Dim iSleepTimes       As Integer:   iSleepTimes = Int(MilliSeconds / SleepyTime)
Dim msLeftOver        As Integer:   msLeftOver = (MilliSeconds - (iSleepTimes * SleepyTime))
Dim dNow              As Double
Dim i                 As Integer

If MilliSeconds < 0 Then MilliSeconds = 0

dNow = Timer
If dNow > (dLastDoevents + (DoEventsRate / 1000)) Or dLastDoevents = 0 Or dLastDoevents > dNow Then
  DoEvents                  'DoEvents if it's been long enough according to the DoeventsRate
  dLastDoevents = Timer
End If

If iSleepTimes > 0 Then
  For i = 1 To iSleepTimes
    Sleep (SleepyTime)      'Sleep at intervals of SleepyTime
    dNow = Timer
    If dNow > (dLastDoevents + (DoEventsRate / 1000)) Or dLastDoevents = 0 Or dLastDoevents > dNow Then
      DoEvents              'DoEvents if it's been long enough according to the DoeventsRate
      dLastDoevents = Timer
    End If
  Next i
End If

If msLeftOver > 0 Then
  Sleep (msLeftOver)        'Sleep for the remainder of milliseconds if needed (ie WaitFor 5)
  dNow = Timer
  If dNow > (dLastDoevents + (DoEventsRate / 1000)) Or dLastDoevents = 0 Or dLastDoevents > dNow Then
    DoEvents                'DoEvents if it's been long enough according to the DoeventsRate
    dLastDoevents = Timer
  End If
End If

【问题讨论】:

  • C++ DLL 是否使用后台线程? (我想不出调用例程必须“等待”另一个例程完成的任何其他情况。)
  • 这是他们自己制作的 WaitFor 函数吗?如果是这样,你可以发布它吗? WaitFor() 可能有一些 DoEVents 不会像固定循环到 500 那样阻止执行。
  • 天哪。我认为那不是他们的功能。我是VB的新手。是的,他们有一个计时器(经过的毫秒)。它调用 DoEvents 直到计时器到时。
  • 他们还在等什么?等待特定时间或循环到特定数字只是为了完成某件事是不好的做法。最好在操作完成时设置标志或引发事件
  • 他们只是在其中添加了等待,因此它不会在“领先于 DLL”时崩溃。向我解释它的高级程序员说这是一个 VB6 问题,这是解决它的唯一方法。我想我只是在仔细检查是否有其他人有这种经验并且可能知道更好的方法。我同意“等待”很糟糕。

标签: debugging dll vb6


【解决方案1】:

在调试模式下,Visual Basic 6 IDE 不会编译为本机代码(它解释 P 代码),因此您的代码的行为与从 exe 运行时崩溃的程度不同。您可以生成使用 P 代码的 .exe,但不建议这样做。 (它在某种程度上减慢了执行速度,但似乎你想减慢速度)。

正如评论部分所述,WaitFor 不是 VB 函数,而 VB6 并不以其简单的多线程功能而闻名。从这里很难找出它崩溃的原因,但众所周知,DoEvents 会导致崩溃due to stack overflows

由于您可以访问这两个代码,我建议修改它们以提供基于事件的机制。如果您不使用 COM 或不想引发 COM 事件,您还可以使用命名管道等替代通信通道来告诉 VB6 工作已完成。

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多