CancelAsync() 呼び出しと RunWorkerAsync() 呼び出しの間に非常に短い間隔しかない場合、VB.net を使用してバックグラウンド ワーカーを停止してから開始するのに問題があります。以下の問題を説明するための例を作成しました。この例の問題は、ボタンが 1 回クリックされてから 2 回続けてクリックされた場合に発生します。基本的に、私が理解しているように、問題はバックグラウンド ワーカーがまだ for ループ (実行に時間がかかるコードを模倣するために含まれている) を反復処理しており、キャンセルが保留中かどうかを確認する機会がまだないことです。
私が使用しようとした解決策は、バックグラウンドワーカーが閉じるのを待ってから、ワーカーを再度開始することです。ただし、この while ループは無期限に繰り返されます。バックグラウンド ワーカーは決して終了しません。メインスレッドをスリープ状態にすると、バックグラウンドワーカースレッドもスリープ状態になると思います。これは正しいです?
質問: バックグラウンド ワーカーを停止し、数分の 1 秒後に再度開始する必要がある可能性がある場合、保留中のキャンセルのチェックを通常よりも頻繁に合理的に行うことができない場合、推奨される方法は何ですか?
アドバイスやコメントは大歓迎です。
Public Class Form1
Dim WithEvents bgWorker As System.ComponentModel.BackgroundWorker = New System.ComponentModel.BackgroundWorker
Friend WithEvents startStopButton As Button = New Button
Dim workerShouldBeRunning As Boolean = False
Sub startStopButton_click() Handles startStopButton.Click
If workerShouldBeRunning Then
bgWorker.CancelAsync()
Else
While bgWorker.IsBusy
Threading.Thread.Sleep(1)
End While
bgWorker.RunWorkerAsync()
End If
workerShouldBeRunning = Not workerShouldBeRunning
End Sub
Sub bgWorker_doWork() Handles bgWorker.DoWork
While Not bgWorker.CancellationPending
Dim sum As Long
For counter = 1 To 100000
sum += counter
Next
Threading.Thread.Sleep(1000)
End While
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
startStopButton.Location = New Point(10, 100)
startStopButton.Size = New System.Drawing.Size(200, 23)
startStopButton.Text = "Click" 'Click to start or stop the background dummy process.
Me.Controls.Add(startStopButton)
bgWorker.WorkerSupportsCancellation = True
End Sub
End Class
編集:
Ross Presser のアドバイスを使用して、サンプル コードを改善しました。ただし、解決策は少し悪いようです。
Public Class Form1
Dim WithEvents bgWorker As System.ComponentModel.BackgroundWorker = New System.ComponentModel.BackgroundWorker
Friend WithEvents startStopButton As Button = New Button
Dim workerShouldBeRunning As Boolean = False
Dim startQueued As Boolean = False
Sub startStopButton_click() Handles startStopButton.Click
If workerShouldBeRunning Then
bgWorker.CancelAsync()
Else
If bgWorker.IsBusy Then
startQueued = True
Else
bgWorker.RunWorkerAsync()
End If
End If
workerShouldBeRunning = Not workerShouldBeRunning
End Sub
Sub bgWorker_doWork() Handles bgWorker.DoWork
While Not bgWorker.CancellationPending
Dim sum As Long
For counter = 1 To 100000
sum += counter
Next
Threading.Thread.Sleep(1000)
End While
End Sub
Sub bgWorkerCompleted() Handles bgWorker.RunWorkerCompleted
If startQueued Then
startQueued = False
bgWorker.RunWorkerAsync()
End If
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
startStopButton.Location = New Point(10, 100)
startStopButton.Size = New System.Drawing.Size(200, 23)
startStopButton.Text = "Click" 'Click to start or stop the background dummy process.
Me.Controls.Add(startStopButton)
bgWorker.WorkerSupportsCancellation = True
End Sub
End Class