2

クロススレッド例外エラーを受け取った後、私はMSDNでそれを調べました。クロススレッディング例外 - 呼び出しを使用

私はそこにいくつかのコードを実装しようとしましたが、コールバックを動作させることができません。

addItemCallback d = new addItemCallback(addItem); 

これは以下のaddItem()メソッドにあります。

私は項目のリストをリストボックスに追加しようとしています。最終的には、バックグラウンドが完了した後にすべてが追加されるのではなく、値が見つかるたびにフォームを更新します。私はbackground_doWorkを使用して、それからメソッドを呼び出すと、プログレスバーがランダムスポットでハングアップしてフォームを閉じるには、応答を停止SO FAR

コード1.

private void startWork() 
{   
    progressBar1.Value = 0; 

    progressBar1.Maximum = 901242; 

    backgroundWorker1.RunWorkerAsync();  
} 

private void getList() 
{ 
    if (pathFound) 
    { 
     for (int i = 0; i < numberOfPaths; i++) 
     { 
      Microsoft.Win32.RegistryKey mainPath = secondaryPath.OpenSubKey("application " + Convert.ToString(i)); 

      if (mainPath != null) 
      { 
        this.addItem((string)mainPath.GetValue("Name")); 
      } 

      backgroundWorker1.ReportProgress(i); 
     } 
    } 

    pathListBox.Sorted = true; 
} 

private void addItem(string item) 
{ 
    if (this.pathListBox.InvokeRequired) 
    { 

     //addItemCallback d = new addItemCallback(addItem); 

     //not sure what this callBack is, can't get it to work, Callback isnt found. 

     this.Invoke(d, new object[] { item }); 
    } 

    else 
    { 
     this.pathListBox.Items.Add(item); 
    } 
} 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    getList(); 
} 

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    progressBar1.Value = e.ProgressPercentage; 
} 

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    this.progressBar1.Visible = false; 
} 

WORKは、私は私のようなオブジェクトの例外を取得しますまだ仕事をしようとしている間にフォームを閉じた。

コード2.メソッドを呼び出すのではなく、background_doWorkにすべてのコードを配置すると、プログレスバーが終了することがあります。

この原因は何ですか?

----- CODE 1 -----------

public Form1() 
    { 
     InitializeComponent(); 

     start(); 
    } 

    int number = 900000; 

    public void start() 
    { 
     progressBar1.Value = 0; 

     progressBar1.Maximum = number; 

     backgroundWorker1.RunWorkerAsync(); 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     getList(); 
    } 

    private void getList() 
    { 
     Microsoft.Win32.RegistryKey mainPath = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node"); 

     for (int i = 0; i < number; i++) 
     { 
      Microsoft.Win32.RegistryKey mainPath = secondaryPath.OpenSubKey("application " + Convert.ToString(i)); 

      if (mainPath != null) 
      { 
       this.addItem((string)mainPath.GetValue("Name")); 
      } 

      backgroundWorker1.ReportProgress(i); 
     } 
    } 

    private void addItem(string item) 
    { 
     try 
     { 

      if (this.listBox1.InvokeRequired) 
      { 
       this.Invoke(new Action<string>(addItem), item); 
      } 

      else 
      { 
       this.listBox1.Items.Add(item); 
      } 
     } 

     catch 
     { 
      MessageBox.Show("Error - Closed Object before it finished working."); 
     } 

     //this.steamGamesListBox.Sorted = true; 
    } 

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     progressBar1.Value = e.ProgressPercentage; 
    } 

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     this.progressBar1.Visible = false; 
    } 

------ CODE 2 --------

public Form1() 
    { 
     InitializeComponent(); 

     start(); 
    } 

    int number = 900000; 

    public void start() 
    { 
     progressBar1.Value = 0; 

     progressBar1.Maximum = number; 

     backgroundWorker1.RunWorkerAsync(); 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     Microsoft.Win32.RegistryKey steamApps64 = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"); 

     for (int i = 0; i < number; i++) 
     { 
      Microsoft.Win32.RegistryKey steamApps = steamApps64.OpenSubKey("Steam App " + Convert.ToString(i)); 

      if (steamApps != null) 
      { 
       this.addItem((string)steamApps.GetValue("DisplayName")); 
      } 

      backgroundWorker1.ReportProgress(i); 
     } 
    } 

    private void addItem(string item) 
    { 
     try 
     { 

      if (this.listBox1.InvokeRequired) 
      { 
       this.Invoke(new Action<string>(addItem), item); 
      } 

      else 
      { 
       this.listBox1.Items.Add(item); 
      } 
     } 

     catch 
     { 
      MessageBox.Show("Error - Closed Object before it finished working."); 
     } 

     //this.steamGamesListBox.Sorted = true; 
    } 

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     progressBar1.Value = e.ProgressPercentage; 
    } 

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     this.progressBar1.Visible = false; 
    } 
+0

のC#/ Frameworkのバージョンを使用している追加 - これに応じて、あなたのいずれかを起動するための独自の委任を作成する必要があるか、.net4を使用してアクション – Carsten

+0

のようなものを使用することができます:)(文字制限:Pを) – cheeseman

答えて

3

あなたは、どちらかのカスタムデリゲート型(あなたaddItemCallback)を定義する必要がある、または単に一般的なActionデリゲートを使用します。

private void addItem(string item) 
{ 
    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(new Action<string>(addItem), item); 
     return; 
    } 

    this.pathListBox.Items.Add(item); 
} 

これは通常の最も簡単な方法ですが追加のデリゲート型を導入する必要がないため、これを実行します。

object[]パラメータはparamsキーワードで定義されているため、新しいobject配列をインスタンス化する必要はなく、引数をメソッドに渡すだけです。

+0

これは素晴らしい作品です!私は1つの問題があり、それは私がそれを実行すると、リストが更新されますが、進行中のバーが途中で止まってしまいます。プログラムがthis.Invoke(新しいアクション(addItem)、item)を過ぎて取得できないようです。 - 私はプログラムを終了すると、私はそれを閉じたので、オブジェクトが例外を処理する、なぜここにこだわっているだろうか? – cheeseman

+0

通常、 'Invoke'の代わりに' BeginInvoke'を使ってデッドロックを回避する方が良いです(私の更新された投稿をチェックしてください)。そして、あなたのバックグラウンドメソッドから 'pathListBox.Sorted = true;'も削除します(あなたはそのスレッドのコントロールと対話してはいけません)。しかし、なぜこのことが "中間"で起こるのか分かりません。私はあなたが 'backgroundWorker1.ReportProgress(100 * i/numberOfPaths);'を呼び出すべきであると推測していますが、今はおよそ50のパスがあるので、処理は実際に終了します(これは私の推測です)。これらの変更を行って、どのように変化するかを見てください。 – Groo

+0

この場合、追加されるアイテムの順序は重要ではないので、 'BeginInvoke'を使うことができます。' Sorted'プロパティが 'true'に設定されている場合、それらは挿入されます。一方、問題がある場合は、構造体を完全に変更することができます:ワーカーを使用して 'List'(バックグラウンドスレッド内で実行できます)を記入し、リストを' ListBox'に渡しますあなたは終わった。実行する作業の種類や項目の数によっては、これもうまくいく可能性があります。 – Groo

0

delegate void addItemCallback(string item);

関連する問題