2012-01-17 9 views
2

私はBackgroundWorkerのを使用して、約2つの質問があります。C#でBackgroundWorkerを使用していますか?

1)を使用すると、機能Aと機能Bの機能Aは、BackgroundWorkerのは、現在別のスレッドで関数Bを実行しているので機能Bを実行しますBackgroundWorkerのを作成し、考えてみましょう。関数Bは長時間実行する予定の無限ループです。関数AがBackgroundWorker throughを使用すると、関数Aが戻ります。では、BackgroundWorker(関数A)を開始した関数が返ったので、BackgroundWorkerスレッドはバックグラウンドで実行し続けますか?または、それをインスタンス化した関数が返されたので、関数Bの実行を停止しますか?それが止まったら、関数Aが返っても関数Bが実行し続けるようにするにはどうすればいいですか?

2)BackgroundWorkerによって作成された別のスレッドからWindow Forms Items(つまりTextbox)にアクセスする必要があります。しかし、メインではないスレッドからWindow Forms Itemsにアクセスしようとすると、クロススレッドエラーが発生します。別のスレッドからWindow Forms Itemsに安全にアクセスするにはどうすればよいですか?私は基本的に別のスレッドからテキストボックスを更新し続ける必要があります。私はBackgroundWorkerが "RunWorkerCompleted"と呼ばれるメンバを持っていて、BackgroundWorkerがそのジョブを完了した後に実行されることを知っています。これにより私はWindow Forms Itemsにアクセスできます。しかし、完了後ではなく、スレッドの期間中にWindow Forms Itemにアクセスする必要があります。どのようにしてこれらのスレッドに安全にアクセスできますか?これが不可能な場合は、問題の解決策は他にありますか?

答えて

4

1)BackgroundWorkerは、機能Aが返された後も引き続き実行されます。

2)テキストボックスを更新するイベントハンドラをProgressChangedに作成し、テキストを変更するときはいつでもBackgroundWorkerReportProgressを呼び出します。もちろん、BackgroundWorkerには、ProgressChangedイベントが読み取れるプロパティを設定する必要があります。これは、ProgressChangedイベントハンドラがUIスレッドで呼び出されたために機能します。

+0

ありがとうございます。私はProgressChangedを使用しましたが、それでも私はクロススレッドエラーが発生します。どんな考え? – fdh

+0

あなた(@Farhad)が私から与えられたコードスニペットを試しましたか? –

+0

@Amir Palsapureご協力いただきありがとうございます。あなたの答えは私のために少し複雑です(あなたのせいではありません)。そして、これはちょっと簡単ですので、これを試してみることにしました。私はちょうどC#を始めたので、この答えはちょっと分かりやすいようです。あなたの助けをもう一度ありがとう。 – fdh

1

ジムの答えは正しいです。パート2では

、私はBackgroundWorkerのによって作成された別のスレッドからウィンドウのフォーム項目(すなわち、テキストボックス)にアクセスする必要が

を言いました。

あなたがこの方法をしたいのであれば、今だけ、あなたは何をする必要があります。あなたはあなたの非UIスレッドからテキストボックスにアクセスしているとき、今のような

public static class ControlExtensions 
{ 
    public static void Invoke(this Control control, Action action) 
    { 
     if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null); 
     else action.Invoke(); 
    } 
} 

の下に拡張メソッドを作成することですこのようにする必要があります

txtBox.Invoke(() => { txtBox.Text = "Text Changed from Non-UI thread"; }); 

希望します。 2番目の質問については

1

はさえ、私はかつて同じ問題に直面しました。 _DoWorkメソッドを使用しました。
これはmyGridBindDelegateがデータグリッドビューバインドメソッドを呼び出すデリゲートである。ここ

private void bgwLongTask_DoWork(object sender, DoWorkEventArgs e) 
{ 

    my long task 
    { 
     //in between the long task, i want to udpate the datagrid view dataGridView1 

     if (dataGridView1.InvokeRequired) 
     dataGridView1.Invoke(myGridBindDelegate); 
     else 
     BindDataToGrid(); 
    } 
} 

私のために働いた方法です。

delegate void GridBindDelegate(); 
    GridBindDelegate myGridBindDelegate; 
    myGridBindDelegate = BindDataToGrid; 

    private void BindDataToGrid() 
    { 
     dataGridView1.DataSource = dt; //dt is a datatable which is public 
     dataGridView1.Refresh(); 
    } 

私のために働きました。

関連する問題