デバッグできないような奇妙な例外があります。ワーカースレッドを提案しようとしている人は、仕事でそれらを使用することを禁じられています...なぜそうしないのかと自分自身に尋ねたところ、漠然とした答えとそれを避けるための明確な指示を受け取りました...とにかく...
ライブラリ クラスから直接初期化および表示される別のフォームに進行状況バーを表示することにしました (メイン フォームとは独立して、別のスレッドで実行されます)。このクラスはフォーム自体を初期化しますが、私は 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() にはこの動作がありません...フォームが何かを待っているかのようです...これで私の問題が明確になることを願っています。