Frage

Ich erhalte einen Fehler, der nicht sinnvoll.

Cross-thread operation not valid: Control 'buttonOpenFile' accessed from a thread other than the thread it was created on.

In meiner Anwendung, die UI-Thread feuert backgroundWorker1, die, wenn sie fast vollständig feuert backgroundWorker2 und wartet darauf, es zu vollenden. backgroundWorker1 wartet backgroundWorker2 abgeschlossen ist, bevor es abgeschlossen ist. AutoResetEvent Variablen werden auf Flag verwendet, wenn jeder der Arbeiter abzuschließen. In backgroundWorker2_RunWorkerComplete ist eine Funktion, setzt das Formular-Steuerelemente genannt. Es ist in dieser ResetFormControls() Funktion, wo die Ausnahme ausgelöst wird. Ich dachte, es war sicher Formular-Steuerelemente in der RunWorkerCompleted Funktion zu ändern. Beide Hintergrund Arbeiter aus dem UI-Thread instanziiert. Hier ist ein stark gekürzte, was ich tue:

  AutoResetEvent evtProgrammingComplete_c = new AutoResetEvent(false);
  AutoResetEvent evtResetComplete_c = new AutoResetEvent(false);

  private void ResetFormControls()
  {
     toolStripProgressBar1.Enabled = false;
     toolStripProgressBar1.RightToLeftLayout = false;
     toolStripProgressBar1.Value = 0;

     buttonInit.Enabled = true;
     buttonOpenFile.Enabled = true; // Error occurs here.
     buttonProgram.Enabled = true;
     buttonAbort.Enabled = false;
     buttonReset.Enabled = true;
     checkBoxPeripheryModule.Enabled = true;
     checkBoxVerbose.Enabled = true;
     comboBoxComPort.Enabled = true;
     groupBoxToolSettings.Enabled = true;
     groupBoxNodeSettings.Enabled = true;
  }

  private void buttonProgram_Click(object sender, EventArgs e)
  {
     while (backgroundWorkerProgram.IsBusy)
        backgroundWorkerProgram.CancelAsync();

     backgroundWorkerProgram.RunWorkerAsync();
  }

  private void backgroundWorkerProgram_DoWork(object sender, DoWorkEventArgs e)
  {
     // Does a bunch of stuff...

     if (tProgramStat_c == eProgramStat_t.DONE)
     {
        tProgramStat_c = eProgramStat_t.RESETTING;

        while (backgroundWorkerReset.IsBusy)
           backgroundWorkerReset.CancelAsync();

        backgroundWorkerReset.RunWorkerAsync();
        evtResetComplete_c.WaitOne(LONG_ACK_WAIT * 2);

        if (tResetStat_c == eResetStat_t.COMPLETED)
           tProgramStat_c = eProgramStat_t.DONE;
     }
  }

  private void backgroundWorkerProgram_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
     // Updates form to report complete.  No problems here.

     evtProgrammingComplete_c.Set();
     backgroundWorkerProgram.Dispose();
  }

  private void backgroundWorkerReset_DoWork(object sender, DoWorkEventArgs e)
  {
     // Does a bunch of stuff...

     if (tResetStat_c == eResetStat_t.COMPLETED)
        if (tProgramStat_c == eProgramStat_t.RESETTING)
           evtProgrammingComplete_c.WaitOne();
  }

  private void backgroundWorkerReset_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
     CloseAllComms();
     ResetFormControls();
     evtResetComplete_c.Set();
     backgroundWorkerReset.Dispose();
  }

Alle Gedanken oder Vorschläge haben würde möglicherweise geschätzt. Ich bin mit Microsoft Visual C # 2008 Express Edition. Danke.

War es hilfreich?

Lösung

RunWorkerCompleted wird auf dem Thread ausgeführt werden, der die Background gestartet. Da Sie BackgroundWorkers sind Chaining (ab 2 von 1), 2 des RunWorkerCompleted auf 1 Thread ausgeführt wird, nicht der UI-Thread.

Sie werden mit Invoke auf den UI-Thread zu marshall zurück wollen oder das UI-Update 1 des RunWorkerCompleted bewegen.

Mein Vorschlag würde immer für InvokeRequired sein zu überprüfen, wenn die Benutzeroberfläche zu aktualisieren, auf diese Weise brauchen Sie sich keine Sorgen machen über das, was fädelt es herkommt.

Andere Tipps

Background Objekte können nicht verschachtelt werden. Ich empfehle .NET 4.0 Aufgaben, wenn überhaupt möglich verwenden, da sie nisten tun.

Nesting BGWs ist nur möglich durch so etwas wie ActionDispatcher aus der Nito.Async Bibliothek.

Zugriff auf Steuerelemente in einem anderen Thread wird nie THREAD sein.

Ihre Frage ist: „Wie kann ich eine Steuer Zugriff durch den UI-Thread erstellt einen anderen Thread mit“

Die Antwort ist von Ihrer Kontrolle aufruft. Hier ist ein Link , wo Sie ein Codebeispiel sehen können ermöglicht es.

Ist das tun, was Sie brauchen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top