2017-08-14 4 views
-1

BackgroundWorkerを使用して私のためにいくつかのデータを収集し、プログレスバーを表示してGUIがフリーズされないようにする間に自分のフォームでListViewを更新しようとしています。 BackgroundWorkerを使用してListViewを更新しようとすると、クロススレッドエラーが発生します。これを克服するために、私はBackgroundWorkerで一時ListViewを作成し、それを結果に代入し、backgroundWorker1_RunWorkerCompletedからそれを使用して、元のListViewを作成します。BackgroundViewerを正しく使用してListViewを更新する方法[c#.NET 3.5]

#1:_RunWorkerCompletedに別の一時的なListViewを作成することなく、ListViewを更新/表示するためのよりエレガントな方法がありますか?

#2:元のリストビューをbackgroundWorkerの引数として渡す方法はありますか?

私はこれに関するフィードバックをお寄せいただきありがとうございます。

ありがとうございます!

擬似コード

// Original ListView in Form 
ListView orginalListView = new ListView(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ListView backgroundList = new ListView(); 
    foreach(var data in database) 
    { 
     listViewItem = data.value; 
     backgroundList.Items.Add(listViewItem); 
    } 
    e.Result = backgroundList; 
} 


private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
     // Can I avoid needing to create a temp LV ?? 
     ListView tempLV = new ListView(); 
     tempLV = (ListView)e.Result; 


     foreach (ListViewItem item in tempLV.Items) 
     { 
      orginalListView .Items.Add((ListViewItem)item.Clone()); 
     } 
} 

答えて

1

クロススレッドでユーザーインターフェイスを更新するには、新しい 委任を起動する必要があります。起動方法については、こちらのリンクをチェックしてください: Invoke

はい、あなたが別の一時リストビューを必要とせずにエレガントな方法でそれを行うことができます。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    foreach (var data in database) 
    { 
     if (orginalListView.InvokeRequired) 
     { 
      orginalListView.Invoke(new MethodInvoker(delegate 
      { 
       listViewItem = data.value; 
       orginalListView.Items.Add(listViewItem); 
      })); 
     } 
     else 
     { 
      listViewItem = data.value; 
      orginalListView.Items.Add(listViewItem); 
     } 
    } 
} 
+1

おそらく、呼び出し呼び出しを少し説明します。関連する[link](https://msdn.microsoft.com/en-us/library/zyzhdc6b(v = vs.110).aspx)です。 –

+1

クイックレスポンスと説明リンクをありがとう!私はこの方法が私のために働いたことを確認することができます – AlkiZaganiaris

-1

あなたは可能性が高いだけリソースをロックする必要があります。そのスレッドはそれにアクセスしている。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    foreach(var data in database) 
    { 
     listViewItem = data.value; 
     String name = "orginalListView"; 

     lock (((ListView)this.Controls[name])) 
     { 
      //Update UI, invoked because on different thread. 
      Invoke(new MethodInvoker(delegate { ((ListView)this.Controls[name]).Items.Add(listViewItem); })); 
     } 
    } 
} 
+0

なぜ私のランクは下がっていますが、もう1つは非常によく似た回答ですが、 –

+0

私は投票しませんでしたが、私が推測したことは、リソースをロックする必要があると言いましたが、その理由を説明していないということです。私の理解では、それをロックすることは必要ではないでしょうが、私は確かに間違っている可能性があります。スレッドに関しては専門家ではありません。 –

+0

あなたの迅速な対応に感謝します! @ st3_121 – AlkiZaganiaris

関連する問題