Brechen Sie eine Schleife in einer Aufgabe von außen ab

M. Witwe

Auf einer WinForm muss ich kontinuierlich Daten von einer Quelle (in meinem Fall ein USB-Gerät) lesen und die Daten in Etiketten anzeigen. Das Lesen sollte auf Befehl (button_click) gestartet und bei einem weiteren Klick auf die Schaltfläche oder in der Methode form_closing gestoppt werden. Ich habe inzwischen herausgefunden, dass ich dafür verwenden muss, Task.Factoryda ich dort ein erstellen kann CancellationToken. Hier ist mein (Beispiel-) Code bisher:

public partial class Form1 : Form
{
    CancellationTokenSource m_CancellationSource;
    Task m_USBReaderTask;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        m_CancellationSource = new CancellationTokenSource();
        m_USBReaderTask = Task.Factory.StartNew(() => doAsync(m_CancellationSource.Token), m_CancellationSource.Token);
    }

    private void doAsync(CancellationToken ct)
    {
        InitUSBReader();
        while (!ct.IsCancellationRequested)
        {
            int[] data=ReadUSB();
            this.Invoke((MethodInvoker)delegate
            {
                lbOut1.Text = data[0].ToString();
                lbOut2.Text = data[1].ToString();
                lbOut3.Text = data[2].ToString();
                //... and so on...
            });
        }
        CleanupUSBReader(); //this is never happening
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (null != m_CancellationSource)
        {
            m_CancellationSource.Cancel();
            m_USBReaderTask.Wait(); // this always hangs.
        }
    }

}

Offensichtlich stehe ich vor zwei Problemen:

  1. Wenn das festgelegt CancellationTokenist, wird die Aufgabe abgebrochen, aber ich muss aufräumen. Ich möchte nur die 'while'-Schleife beenden. (oder stürzt es ab und keine Fehlermeldung?)
  2. In diesem FormClosingFall muss ich warten, bis die Bereinigung abgeschlossen ist, aber sie blockiert endlos.

Ist mein Ansatz neben meinen beiden Problemen überhaupt richtig oder gibt es einen eleganteren Weg, um meine Ziele zu erreichen? Vielen Dank

Abfahrt

In Bezug auf Ihre erste Ausgabe. Wenn das Token abgebrochen wird, endet die While-Schleife und die CleanupUSBReader()Methode sollte ausgeführt werden. Dies setzt voraus, dass ReadUSB regelmäßig zurückkehrt. Andernfalls benötigen Sie eine Möglichkeit, den Lesevorgang abzubrechen. Wenn Sie die Aufgabe nur beim Schließen des Formulars abbrechen, handelt es sich wahrscheinlich um einen Deadlock (siehe zweiter Absatz). Wenn der ReadUSB zurückkehrt, Sie keinen Deadlock haben und die Bereinigungsmethode immer noch nicht erreichen, muss es ein anderes Problem geben, wie z. B. eine Ausnahme irgendwo.

In Bezug auf Ihre zweite Ausgabe. Das Problem ist, dass Sie aufrufen this.Invoke, dies ist synchron, dh es wird der Code auf dem Hauptthread ausgeführt und gewartet, bis er abgeschlossen ist. Wenn das Formular geschlossen wird, fordert der Hauptthread die Aufgabe ab, abgebrochen zu werden, und wartet, bis sie abgeschlossen ist. Die Aufgabe wartet jedoch darauf, dass der Hauptthread die Benutzeroberfläche aktualisiert. Dies führt zu einem Klassifizierungs-Deadlock. Eine Lösung sollte die Verwendung sein this.BeginInvoke, da dies den Hauptthread auffordert, die Benutzeroberfläche zu aktualisieren, aber nicht auf das Ergebnis wartet. Lesen Sie mehr in Invoke vs BeginInvoke

Es gibt eine allgemeine Empfehlung, die Verwendung zu vermeiden, task.Wait()da dies sehr leicht zu solchen Deadlocks führt. Es ist möglicherweise eine gute Idee, das Warten auf die Aufgabe zu überspringen, wenn das Formular geschlossen wird. Oder um das Schließen awaitder Aufgabe abzubrechen und das Formular nach dem Warten zu schließen.

Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.

Bei Verstößen wenden Sie sich bitte [email protected] Löschen.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel

TOP Liste

  1. 1

    MongoDB eingebettetes Dokument unterscheiden und filtern

  2. 2

    Wie aktualisiere ich ein Feld in einer Raumdatenbank mit einem Repository und einem Ansichtsmodell?

  3. 3

    Interpolieren Sie mit Python die 2D-Matrix entlang der Spalten

  4. 4

    So verschieben Sie ein Bild in Flutter/Dart mit einem Draggable

  5. 5

    Wie vermeide ich, dass die gesamte App neu geladen wird, wenn Nav.Link von React-Bootstrap verwendet wird?

  6. 6

    Wie verwende ich Format-Table ohne Abschneiden von Werten?

  7. 7

    numpy: Berechnen Sie die Ableitung der Softmax-Funktion

  8. 8

    Warum funktioniert das Umgebungslicht in diesem Beispiel nicht?

  9. 9

    Ersetzen von Einträgen in einer Spalte durch eine andere basierend auf der Bedingung

  10. 10

    So berechnen Sie die Verfügbarkeit von Anwendungen (SLA)

  11. 11

    Wie ändere ich die Farbe des Symbols und des Textes, wenn ich den Bildschirm im Navigator der unteren Registerkarte in "Reaktion native" ändere?

  12. 12

    spring-data-jpa: ORA-01795: Die maximale Anzahl von Ausdrücken in einer Liste beträgt 1000

  13. 13

    Wie lade ich eine Datei herunter, ohne den Typ oder Dateinamen zu kennen?

  14. 14

    Excel VBA - Erstellen Sie mehrere Dateien aus Daten in mehreren Arbeitsmappen

  15. 15

    Docker bleibt beim Ausführen von time.sleep (1) in einer Python-Schleife hängen

  16. 16

    Überprüfen Sie, ob der ausgewählte Wert 'YES' ist, wenn ja, aktivieren Sie ein Steuerelement mit Javascript

  17. 17

    Python gibt einen Fehler aus, dass eine Datei nicht vorhanden ist, wenn dies eindeutig der Fall ist

  18. 18

    TypeAhead.js zeigt keine Ausgangsschienen an?

  19. 19

    Pandas rufen einen Wert basierend auf dem Index ab

  20. 20

    Aktualisieren des Werts im Json-Objekt in Python

  21. 21

    Das Abrufen von einer URL zeigt einen Fehler in der Konsole an, auch nachdem er abgefangen wurde?

heißlabel

Archiv