2016-08-09 11 views
0

長時間実行しているバックグラウンドワーカーがいます。タスクはファイルのリストを通過し、私は私たちがいるファイルを使用してユーザーを更新したい。私はpanel1.textという名前のラベルを持つツールストリップを持っています。プログレスバーは機能していますが、ラベルはProgressChangedメソッドで変更されていません。つまり、File1の処理が処理され、File2の処理に変更されますが、Processingのデフォルトにとどまります。ラベル付きプログレスバー - ProgressChangedでラベルを更新できません

private void btnProcess_Click(object sender, EventArgs e) 
    { 
     toolStripProgressBar1.Visible = true; 
     toolStripProgressBar1.Maximum = 1000000000; 
     panel1.Text = "Processing "; // this appears properly 
     BackgroundWorker worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(processFiles); 
     worker.ProgressChanged += ProgressChanged; 
     worker.RunWorkerAsync(); 
     while (worker.IsBusy) 
     { 
      // the reason for this is because nothing can happen until the processing is done 
      toolStripProgressBar1.Increment(1); 
     } 
     // more processing 
    } 

    private void ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     panel1.Text = "Processing "+ e.UserState.ToString(); <<<---- This is Not Updating panel1.Text but it evaluates properly 
    } 

    private void processFiles(object sender, EventArgs e) 
    { 
     int retVal = 0; 
     foreach (string fileName in listBox1.Items) 
     { 
      ProgressChangedEventArgs ea = new ProgressChangedEventArgs(1,fileName); 
      ProgressChanged(this, ea); 

      // do more processing 

     } 
    } 

私は助けていただきありがとうございます。

+1

更新しないという意味ですか?ラベルのテキストが変更されていないか、または何ですか? – Rahul

+2

'while(worker.IsBusy) 'ループは、基本的にUIスレッドがペイント(そして、それだけでなく)メッセージを処理するのを防ぎます。 –

+0

はい - ラベルテキストは変更されません。ループ内のラベルを更新する必要があるようです。 – Missy

答えて

1

にそれらの後に処理を移動する必要があります。タスクを使用して新しいスレッドを作成し、コントロールが別のスレッドにある場合はDispatcher.BeginIvokeを使用する必要があります。ボタンのクリックなどが起こっていることをAsyncキーワードでマークして、非同期にするようにしてください。

例:Labelクラスの内部次に

Await Task mytask = Task.Run(() => 
          for(var i = 0; i < 1000; i++) 
          { 
           Label.Dispatcher.BeginInvoke(() => 
                   UpdateMe(int i, LabelClass/Component class/component)}); 

またはどこラベルは次のとおりです。

Public void UpdateMe(int i, LabelClass class) 
{ 
    class.label.content = Cint((i/Total)*100); 
    Thread.Sleep(500); 
} 

なUIに値をバインドだけでなく、それを行うには、他の方法がありますが、これは、なぜ動作していないのか、どのように他のスレッドで動作するのかをより深く理解できるようになります。

あなたは本当に視覚的に理解コールを取得したい場合:

`Console.WriteLine($"Current Thread ID: System.Threading.Thread.CurrentThread.ManagedThreadId}");` 

右の[タスクに入る前に---それは、タスクの内部で再びそれを呼び出すあなたのメインスレッドID を与えるだろう。..これによりセカンダリスレッドIDが与えられます。
右ディスパッチャの呼び出しの前に:、あなたがアクセス権を持っている場合は、それが偽表示されますされていない場合

Console.WriteLine($"Do I have access to the label on this thread? {Label.Dispatcher.CheckAccess()}"; 

はそれが...、真表示されますそのほかのスレッドが所有しているので、あなたのケースでは、それが偽表示されますが、ディスパッチャを使用して、別のスレッドでそのスレッドで作業を行うことができます。

また、バックグラウンドワーカーを使用せずにタスクを使用することをお勧めします。タスクはすべてバックグラウンドワーカーが行います。問題は少なく、作業が簡単です...

http://blog.stephencleary.com/2013/09/taskrun-vs-backgroundworker-conclusion.html

+0

そのすばらしい記事ありがとう、Matt – Missy

1

Ivanによって既にコメントされているように、whileループwhile (worker.IsBusy)を削除すると、UIスレッドがさらに処理されなくなります。同様に、あなたは、あなたのコメントパーtrue

worker.WorkerReportsProgress = true; 
    worker.ProgressChanged += ProgressChanged; 
    while (!worker.IsBusy) 
    { 
     worker.RunWorkerAsync(); 
    } 

WorkerReportsProgressを有効にするには、別のプロセスによってブロックされているのと同じスレッドを使用しているBackgroundWorker.RunWorkerCompleted Event

+0

私はそれを試してみましょう。 – Missy

+0

@Missy、続行したい場合は、answerで編集し、TPLを使用することを検討してください。 – Rahul

+0

完全なイベントについての良い考え – Missy

関連する問題