1

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
4

2 に答える 2