Autor Beitrag
WSS-130
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24



BeitragVerfasst: Fr 25.01.13 14:58 
Hi,

ich überarbeite gerade mein Programm und möchte den Export im BackgroundWorker ausführen.

Beim klicken des "Export"-Buttons, wird also:
ausblenden C#-Quelltext
1:
background_Export.RunWorkerAsync(exportFile);					


Nun sollte wenn ich diese Methode debugge das Programm doch in:

ausblenden C#-Quelltext
1:
2:
3:
4:
public void background_Export_DoWork(....)
{

}


springen, so dass ich den Code nachvollzeihen kann....
Das macht der Debugger aber nich. :-(


Zuletzt bearbeitet von WSS-130 am Di 29.01.13 10:14, insgesamt 1-mal bearbeitet
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 25.01.13 15:32 
Wird sie aufgerufen aber du kannst nicht debuggen oder wird die gar nicht aufgerufen?
WSS-130 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24



BeitragVerfasst: Fr 25.01.13 15:58 
Hat sich shcon erledigt. Danke Trotzdem.
Wurde von anfang an aufgerufen, nur wurde zuerst der eine Thread gedebuggt, danach der nächste.

Für Leute mit ähnlichem Problem, komfortable lässt sich das dann mit einem Breakpoint in der DoWork Methode debuggen.

Viele Grüße
WSS-130 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 24



BeitragVerfasst: Di 29.01.13 10:43 
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:
ausblenden 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)
{
  //  Zeit messen:
  //watch.Reset();
  //watch.Start();                                  // nur zum Zeitmessen
  //  Zeit messen

  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:
ausblenden volle Höhe C#-Quelltext
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";
    //MessageBox.Show("Einlesen beendet in: " + watch.ElapsedMilliseconds + "ms");
  }
}
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
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 29.01.13 11:00 
Folgendes aus der MSDN Doku zu Cancel Async.
Zitat:

CancelAsync fordert das Abbrechen des anstehenden Hintergrundvorgangs an und legt die CancellationPending-Eigenschaft auf true fest.

Über den Aufruf von CancelAsync kann die Worker-Methode ihre Ausführung anhalten und sich selbst beenden.Der Worker-Code sollte regelmäßig prüfen, ob die CancellationPending-Eigenschaft auf true festgelegt wurde.