Ungültige Cross-Thread-Operationen von BackgroundWorker2_RunWorkerCompleted in C #
-
26-09-2019 - |
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.
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?