BackgroundWorker 重たい処理のキャンセル 2005.NET 
	
	 
	
	 
重たい処理がキャンセルできるようにするには、Application.DoEvents()をかまして行う方法があるが、 
BackgroundWorkerコントロールができたのでこれを使う方法も選べるようになった。 
 
BackgroundWorkerの良い点。 
その名の通りバックグランドで行われるので実行中にフォームをクリックすると実行が止まる 
ということがなくなり、よりスマートなUIが簡単に実現できるという点にあるようだ。 
 
以下のサンプルはフォームにボタン2個、ラベル1個、 
BackgroundWorkerコンポーネント1個(GUIからプロパティー 途中経過有効 キェンセル有効 をTrueにしたもの。)を追加して書いたもの 
 
''Imports System.ComponentModel 'こいつをインポートしておいてもよい 
 
 
Public Class Form1 
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
        'スタートさせる 
        Me.Button1.Enabled = False '二重実行は厳禁なのでこうしておく 
        BackgroundWorker1.RunWorkerAsync(1000) 'これで重たい処理がバックグランドで実行される。 
        '1000は単なるパラメータ こうやって渡すことができる。 
 
    End Sub 
 
    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork 
        'ここに重たい処理を書く 
        'ここで実行される処理は バックグランドで行われるので このルーチンからユーザインターフェイスは操作できない 
        'でも途中経過を知らなければバックグランドを使う意味がない。 
        'でコントロールにProgressChangedイベントがあるというわけ 
 
 
        'BackgroundWorker1.RunWorkerAsync(1000)の1000をiに取得する。 
        'ArgumentはHelpには非同期操作の引数を表す値を取得します。と書いてある。おまじないだ。 
        Dim i As Integer = CType(e.Argument, Integer) 
        Dim j As Integer = 0 
 
        'senderにバックグランドスレッド(オブジェクト)が入ってくるので取り出す。 
        Dim back As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker) 
 
 
        Do Until j = i 
            If back.CancellationPending = True Then 
                'キャンセルボタンが押されたか調査 
                e.Cancel = True 
                Exit Do 
            End If 
            ' ''Application.DoEvents() 'これでは制御できない 
            ' ''Application.DoEvents() 'これでは制御できない 
            ' ''Application.DoEvents() 'これでは制御できない 
            ' ''Application.DoEvents() 'これでは制御できない 
            ' ''Application.DoEvents() 'これでは制御できない 
            ' ''Application.DoEvents() 'これでは制御できない 
            ' ''Application.DoEvents() 'これでは制御できない 
 
            System.Threading.Thread.Sleep(10) '指定したミリ秒数の間現在のスレッドをブロックします。これを書かないとキャンセルボタンは押せない 
            'ということはトータルの実行速度は遅くなる [1]だとキャンセルボタンは押せない 最小は[10]ぐらいか? 
            '0を指定すると途中停止になるらしいが止まらない 
 
            ''Me.Label1.Text = j & "%" 'これはNG "有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'Label1' がアクセスされました。" が出る 
            back.ReportProgress(j) '何パーセント終了したか0~で入れるらしいが100を超えてもエラーは起きない Integerの2,147,483,647まで  
            j += 1 'インクリメント 
            Debug.WriteLine(j) 
 
        Loop 
 
        e.Result = "終了" 
    End Sub 
 
    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged 
        '途中経過の情報が入ってくる 
        Me.Label1.Text = e.ProgressPercentage & "%" 
        Debug.WriteLine(Me.Label1.Text) 
    End Sub 
 
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted 
        'すべて終了したら入って来る 
        If e.Cancelled = True Then 
            Me.Label1.Text = "キャンセルしました" 
        Else 
            Me.Label1.Text = e.Result 
        End If 
 
    End Sub 
 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
        ’キャンセルボタン 
        BackgroundWorker1.CancelAsync() 
 
    End Sub 
End Class
 
  |  
  
	
	
	 
	
	
		
		
	 
	 |