0

別のクラス内で関数を呼び出すバックグラウンドワーカーがいます。このプロセスは、フロントエンドからボタンをクリックすることでいつでもキャンセルする必要がある場合があります。CancelAsync()を使用してみましたが、効果がありません。cofunds_downloadfilesは、私が呼び出している関数です。プロセスをキャンセルするにはどうすればよいですか?

TIA。

Private Sub btnProcessdld_Click(sender As System.Object, e As System.EventArgs) Handles btnProcessdld.Click

    Dim cfHelper As New CoFundsHelper

    If btnProcessdld.Text = "Process" Then
        btnProcessdld.Text = "Cancel"

        If chkDailyFiles.Checked = False And chkWeeklyFiles.Checked = False Then
            MessageBox.Show("Please select which files you want to download")
        Else

            lblProgress.Text = "Processing...if you are downloading weekly files this may take a few minutes"
            uaWaitdld.AnimationEnabled = True
            uaWaitdld.AnimationSpeed = 50
            uaWaitdld.MarqueeAnimationStyle = MarqueeAnimationStyle.Continuous
            uaWaitdld.MarqueeMarkerWidth = 60

            _backGroundWorkerdld = New BackgroundWorker
            _backGroundWorkerdld.WorkerSupportsCancellation = True
            _backGroundWorkerdld.RunWorkerAsync()

        End If

    ElseIf btnProcessdld.Text = "Cancel" Then
        btnProcessdld.Text = "Process"
        _backGroundWorkerdld.CancelAsync()
        uaWaitdld.AnimationEnabled = False

    End If

Private Sub StartProcessdld(ByVal sender As Object, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) Handles _backGroundWorkerdld.DoWork

    Dim cfHelper As New CoFundsHelper
    cfHelper.ConnString = PremiumConnectionString
    Dim dateValue As String

    Dim weekly As Boolean = False
    Dim daily As Boolean = False

    If dtePicker.Value IsNot Nothing Then
        dateValue = Format(dtePicker.Value, "yyyyMMdd")

        If chkWeeklyFiles.Checked = True Then
            weekly = True
        End If
        If chkDailyFiles.Checked = True Then
            daily = True
        End If

        cfHelper.Cofunds_DownloadFiles(dateValue, weekly, daily)

    Else
        Throw (New Exception("Date Field is empty"))
    End If
End Sub
4

2 に答える 2

1

CancelAsync実際にはワーカーのキャンセルを行わないCancellationPending = Trueため(セットするだけです)、基本的に関数でBackGroundWorkerの状態を確認する必要があります。

Do While Not worker.CancellationPending
    'some long running process
Loop

ただし、これは100%信頼できるわけではないため、独自のキャンセルフラグを使用する方が安全な場合があります。

于 2012-06-29T14:17:47.273 に答える
1

基本的に、次のことができます。

  • DoWorkサブで、cancellationpendingプロパティをテストします
  • それが本当なら、あなたは単にその関数を呼び出さず、多分e.Cancelled = trueそれを入れて、RunWorkerCompletedでこれをチェックして、あなたがしなければならないことを決定します。
  • それをキャンセルする必要がある場合は、それをStop()正確に実行するサブをクラスに作成するだけです-プロシージャを停止します。次に、次のように呼び出す必要があります

    Me.Invoke(Sub()
              myClass.Stop()
           End Sub)
    
  • メインスレッドからの呼び出しが戻るまで、バックグラウンドワーカーを一時停止する必要がある場合があります。これは、セマフォを使用して行います。これを Private chk As New Semaphore(1,1,"checking1") 、メインスレッドとバックグラウンドワーカーの両方に対するグローバル変数として配置します。

  • chk.WaitOne()backgroundworker_doWorkでは、実行する必要のある行の後のようなセマフォを使用します。
  • クラスのメソッドで、コンピューティングが終了したら、a.Release

セマフォは、結果を確実に待つ必要がある場合にのみ必要です。これはマルチスレッドの目的をやや損なうものですが、メインスレッドを待つ前にワーカーで他のアクションを実行できます(他のスレッドで別のスレッドを開始するなど)。

それ以外は、stopメソッドを呼び出すだけで十分です。コードを分析する時間がなかったので申し訳ありませんが、正しい方向に進んでいただければ幸いです。

于 2012-06-29T17:28:33.487 に答える