BackgroundWorker Thread beenden



  • Hallo,

    ich verwende das Windows Forms Framework und habe einen BackgroundWorker, der Werte in einer Form aktualisieren soll. Ich verwende folgenden Code

    private void bgwUpdateValues_DoWork(object sender, DoWorkEventArgs e)
            {
                while (!bgWorkerUpdateValues.CancellationPending)
                {
                    tbMaxLadestrom.Invoke(new MethodInvoker(setMaxLadestrom));  
                    tbMaxLadespannung.Invoke(new MethodInvoker(setMaxLadespannung));
                    Thread.Sleep(100);
                }
            }
    

    Wenn ich meine Form schließe soll der Thread beendet werden. Deshalb rufe ich in der "FormClosing" Methode meiner Form

    bgWorkerUpdateValues.CancelAsync();
    

    auf.
    Ich habe bei meinem Thread das Attribut "WorkerSupportsCancellation" auf true gesetzt.
    Wenn ich meine Form schließe bekomme ich immer wieder diesen Fehler:
    "Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde."
    Ich denke dass die Methode noch ein letztes Mal ausgeführt wird obwohl die Form geschlossen ist.

    Jetzt meine Frage: Warum?^^ Und was kann ich dagegen tun?

    Wenn ich mit dem Debugger schaue wenn der Fehler kommt sehe ich, dass bgWorkerUpdateValues.CancellationPending = true ist. Trotzdem bin ich in der Schleife...

    Viele Grüße
    MeinAccount



  • Nächster Versuch. Es ist leicht hierbei Deadlocks zu bauen oder Pfade zu übersehen, die nicht zum gewünschten Ergebnis führen

    public partial class Form1 : Form
    {
    	bool cancelRequested = false;
    
    	public Form1()
    	{
    		InitializeComponent();
    		backgroundWorker1.RunWorkerAsync();
    	}
    
    	private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    	{
    		while (!backgroundWorker1.CancellationPending)
    		{
    			Thread.Sleep(1000);
    			Invoke(new Action(() => Console.WriteLine("ticktack")));
    		}
    	}
    
    	private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    	{
    		if (cancelRequested)
    			Close();
    	}
    
    	private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    	{
    		if (backgroundWorker1.IsBusy && !cancelRequested)
    		{
    			Hide();
    			cancelRequested = true;
    			e.Cancel = true;
    			backgroundWorker1.CancelAsync();
    		}
    	}
    }
    


  • Vielen Dank für die Antwort. Inzwischen habe ich mein Problem aber deutlich einfacher gelöst bekommen. Verwendet man die ProgessChanged Methode anstatt der DoWork Methode, kann man komplett auf Invoker verzichten. Da wird das dann alles vom System gemanaged. Das ganze sieht dann so aus:

    private void bgwUpdateValues_DoWork(object sender, DoWorkEventArgs e)
            {
                while (!bgWorkerUpdateValues.CancellationPending)
                {
                    bgWorkerUpdateValues.ReportProgress(1, this);   
                    Thread.Sleep(100);
                }
            }
    
            private void bgWorkerUpdateValues_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                tbMaxLadestrom.Text = canKlasse.getMaximumChargeCurrent().ToString();
                tbMaxLadespannung.Text = canKlasse.getMaximumChargeVoltage().ToString();
            }
    

    Gruß
    MeinAccount


Anmelden zum Antworten