Das Multithreading über den BackgroundWorker habe ich nich nicht ganz im Griff.
Und zwar wird meine Export Methode wie gewünscht in einem anderen Thread ausgeführt. Dies soll dann über die CancelAsync-methode des BgW abgebrochen werden können. Was nicht möglich ist.
Hier der Teil meines Codes, der den BgW startet und auch wieder abbrechen soll.
GUI:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| private void button_startcancel_Click(object sender, EventArgs e) { if (background_Export.IsBusy) { background_Export.WorkerSupportsCancellation = true; this.background_Export.CancelAsync(); button_startcancel.Text = "Start"; } else { background_Export.RunWorkerAsync(tree_select.SelectedNode); button_startcancel.Text = "Cancel"; } } |
BgW:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51:
| private void background_Export_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) MessageBox.Show("Error: " + e.Error.Message); else if (e.Cancelled) MessageBox.Show("Export canceled."); else { button_startcancel.Text = "Start"; } } private void background_Export_ProgressChanged(object sender, ProgressChangedEventArgs e) { export.CurrentState state = (export.CurrentState)e.UserState; } private void background_Export_DoWork(object sender, DoWorkEventArgs e) {
dbMap myDbMap = new dbMap();
System.ComponentModel.BackgroundWorker worker; worker = (System.ComponentModel.BackgroundWorker)sender; export exportData = new export();
TreeNode selected = (TreeNode)e.Argument;
if (selected == null) { MessageBox.Show("Bitte Datei auswählen"); } else { foreach (dataset element in data) { if (element.callDatasetName == selected.Text) { foreach (string path in element.callPathMap) { myDbMap.Import(path); } myDbFlow.ErzeugenAGK(element.callDatasetName, ref myDbMap);
if (checkBox_csv.Checked) exportData.exportCSV(myDbSignFlow.getContainer, saveFolder + element.callDatasetName + ".csv"); if (checkBox_xls.Checked) exportData.exportXLS(myDbSignFlow.getContainer, saveFolder + element.callDatasetName + ".xlsx"); } } } } |
Etwas Erklärung:
Die button_startcancel_Click(...) Methode läuft im Hauptthread. Der Button steuert sowohl den Start des Exports (background_Export.RunWorkerAsync(...)), wie auch das Abbrechen (backgrund_Export.CancelAsync().
Wenn ich ein Export starte und dann auf den Button klicke, is "IsBusy"= true und die CancellationPending wird ebenfalls auf true gesetzt. Der Text des buttons wechselt wieder auf Start.
Die CancelAsync wird aber wohl nicht bis zum Ende ausgeführt und das Programm springt nach dem ausführen der button_startcancel-Click Methode direkt in "background_Export_RunWorkerCompleted(...)". Das Event "Canceled" des Workers ist false.
Und entsprechend wird auch die Datei erzeugt....
Das ist mein erstes Mutlithreading Programm. Bei MSDN habe ich bisher was über Racebedingungen und Deadlocks gelesen. Löse ich eine Racebedingung aus? Oder ist der Grund, dass das Abbrechen nicht funktioniert?
Danke für eure Hilfe!
Grüße