我有一个奇怪的异常,我似乎无法调试。对于任何要建议工作线程的人,我都被禁止在工作中使用它们......我问自己为什么不这样做,并收到一个模糊的答案和明确的指示来避免它......无论如何......
我决定我想在一个单独的表单上有一个进度条,该表单被初始化并直接从我的库类中显示(独立于主表单并在不同的线程上执行)。即使此类初始化表单本身,我仍然使用 control.InvokeRequired 和 control.Invoke,因此我可以在其他地方重用该表单。以下是用于初始化进度条:
Public Sub InitializePB(ByVal _Maximum As Integer, ByVal _Step As Integer, ByVal _StartValue As Integer, ByVal _Style As Windows.Forms.ProgressBarStyle)
If Me.InvokeRequired Then
'Different thread - invoke delegate
pb_Progress.Invoke(Sub() InitializePB(_Maximum, _Step, _StartValue, _Style))
Else
'Same thread - set values
pb_Progress.Minimum = 1
pb_Progress.Maximum = _Maximum
pb_Progress.Step = _Step
pb_Progress.Value = _StartValue
pb_Progress.Style = _Style
Me.Refresh()
End If
End Sub
现在对于阶跃函数:
Public Sub PerformStepPB()
If Me.InvokeRequired Then
'Different thread - invoke delegate
pb_Progress.Invoke(Sub() PerformStepPB())
Else
'Same thread - perform step
pb_Progress.PerformStep()
Me.Refresh()
End If
End Sub
现在以下是我启动包含进度条的表单然后发送步骤调用的测试代码:
pbForm = New frmProgress(_OwnerDesktopLoc)
pbForm.Show()
pbForm.InitializePB(100, 1, 1, Windows.Forms.ProgressBarStyle.Blocks)
Dim msElapsedVals As Integer = 0
While msElapsedVals <= 100
pbForm.PerformStepPB()
Thread.Sleep(100)
msElapsedVals += 1
End While
pbForm.Close()
pbForm.Dispose()
While Not pbForm.IsDisposed
Thread.Sleep(100)
End While
Exit Sub
到目前为止一切顺利......您会注意到,每次调用 step 方法时,我都会为进度条表单调用 Form.Refresh 方法。我最终这样做了,因为当表单启动时,它会在几个进度条步骤后崩溃。在这个时间点,表单确实显示而没有崩溃(因为刷新),除非我单击它崩溃的表单(并且 Visual Studio 没有捕获到异常)。奇怪的是,库类中用于更新进度条的代码继续没有任何问题,就好像问题只是与 Win32 窗口有关。这是与崩溃相关的 Windows 消息:
描述:一个问题导致该程序停止与 Windows 交互。问题签名:问题事件名称:AppHangB1 应用程序名称:DL_RDS_Sort.vshost.exe
我尝试从主表单线程启动表单,但结果相同。我不知道发生了什么......任何帮助将不胜感激=D
更新事物的确切调用方式:
从 MainForm 开始,线程以库类中定义的子例程的地址开始:
Private Sub but_Sort_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles but_Sort.Click
Me.Sorter.OwnerDesktopLoc = New Drawing.Point(Me.DesktopLocation.X + CInt(Me.DesktopBounds.Width / 6), Me.DesktopLocation.Y + CInt(Me.DesktopBounds.Height / 2))
'Start sorting thread
Me.sortThread = New Threading.Thread(AddressOf Me.Sorter.Sort)
Me.sortThread.Start()
然后在这个线程的例程中,我正在测试表单的初始化并调用我为更新性能栏属性而编写的方法(如前所示):
Public Sub Sort()
Try
IIf(_OwnerDesktopLoc = Nothing, useProgressBar = False, useProgressBar = True)
'TESTING//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
pbForm = New frmProgress(_OwnerDesktopLoc)
pbForm.Show()
pbForm.InitializePB(100, 1, 1, Windows.Forms.ProgressBarStyle.Blocks)
Dim msElapsedVals As Integer = 0
While msElapsedVals <= 100
pbForm.PerformStepPB()
Thread.Sleep(100)
msElapsedVals += 1
End While
pbForm.Close()
pbForm.Dispose()
While Not pbForm.IsDisposed
Thread.Sleep(100)
End While
Exit Sub
'TESTING//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
请注意,测试区域后面还有更多代码,但它从未被调用,并且不会在此问题中发挥作用,因为我退出了子例程。我通常使用 ShowDialog 但这会停止执行,这不是我想要的。
一些值得一提的事情: -frmProgress 将 ControlBox 属性设置为 false。-frmProgress 的 FormBorderStyle 设置为 FixedDialog
另外:当我使用 Show() 方法时,当我将鼠标悬停在显示的表单上时,会出现 Windows“忙圈”光标。ShowDialog() 没有这种行为......好像表单正在等待什么......希望这能澄清我的问题。