Aufgabe für x Zeit warten und Fortschritt melden

8

Ich brauche ein besseres Design zum Schlafen Task als Thread.Sleep, verwende ich die Task-Klasse.

In meiner wpf-App starte ich eine Aufgabe, diese Aufgabe führt noch ein paar Aufgaben aus, jede dieser Aufgaben zuerst Anmeldung und Internet-Website, nach der Anmeldung müssen sie einige Sekunden warten und den Benutzer informieren, wenn sie weiter fortfahren und das ist mein Problem, denn mit Thread.Sleep kann ich den Fortschritt nicht melden.

Es gibt mehr Funktionen als login, es ist etwa 5-6, alle von ihnen fordern eine Internet-Ressource, und zwischen ihnen muss eine Ruhezeit mit der verbleibenden Zeit Bericht senden tun gui, diese 5-6 Funktion sind alle in eine Aufgabe, aber es könnte viele Aufgaben geben.

Was ich brauche, ist, die Aufgabe warten zu lassen, aber auch, dass sie Updates über die verbleibende Zeit sendet, um mit der GUI fortzufahren.

Haben Sie irgendwelche Ideen für dieses Problem, wie können Sie es besser machen? Vielleicht haben Sie schon einige Entwurfsmuster für ein solches Problem?

Ich habe auch gehört, dass die Verwendung von Thread.Sleep eine schlechte Design-Praxis ist.

BEARBEITEN: Niemand weiß es? Was ist mit einer Art von selbstständigen Timer mit Thread warten wie waithandle, autoresevent, irgendjemand?

    
Programista 06.11.2011, 19:17
quelle

4 Antworten

1

Vergessen Sie nicht, Thread.Sleep zu verwenden. Führen Sie stattdessen Ihre Aufgabe in einem Hintergrundthread aus, und verwenden Sie ein WaitHandle mit einem AutoResetEvent. (Links: WaitHandle / WaitOne / AutoReset )

Ihr Hintergrund-Thread kann Aktualisierungen an Benutzerschnittstellen mit asynchronen Delegaten senden, aber der aufrufende Thread wartet darauf, bis eines der beiden Dinge passiert:

1) Ihr Thread meldet, dass er seine Aufgabe mithilfe von yourwaithandle.Set () abgeschlossen hat.

oder

2) die wartenden Thread-Timeouts (der Timeout-Wert wird als Parameter für die WaitOne () -Methode gesetzt).

    
Lauri I 15.11.2011, 12:43
quelle
6

Die Lösung besteht darin, sie als asynchronen Rückruf und nicht als synchrone Wartezeit zu behandeln. Wenn Sie sich im Async CTP befinden, wäre der richtige Weg:

async item => { await Task.Delay(1000); Process(item); }

Dies scheint auch ein idealer Anwendungsfall für DataFlow oder Rx zu sein.

Reaktive Erweiterungen verwenden:

%Vor%

Beim Aufruf von Track(timeout: 5, frequency: 1, item: "http://example.com/?") lautet die ausgegebene Ausgabe:

%Vor%     
Asti 09.11.2011 10:28
quelle
1

Machen Sie jede Funktion zu einer separaten Aufgabe, anstatt eine einzige Aufgabe auszuführen, die alle diese sechs Funktionen ausführt (Login usw.). Sie können dann eine Prioritätswarteschlange nach Zeit geordnet erstellen. Wenn Sie eine dieser Meta-Aufgaben starten möchten, legen Sie die erste Funktion zusammen mit den Statusdaten (z. B. URL, Benutzer-ID, Kennwort usw.) in eine Warteschlange.

Wenn jede Funktion abgeschlossen ist, wird die nächste auszuführende Funktion in die Warteschlange gestellt. Wenn also die ersten beiden Funktionen login und get_data sind, müssten Sie:

%Vor%

Wenn die letzte Funktion ausgeführt wird, werden die Ergebnisse irgendwo veröffentlicht.

Sie können dann einen Timer einrichten, der die Warteschlange 10 Mal pro Sekunde abfragt (oder die nächste Tick-Zeit des Timers aktualisiert, sobald etwas zur Warteschlange hinzugefügt wird). Es kann einzelne Aufgaben nach Bedarf starten.

Das neue Async-CTP hat vielleicht schon so etwas: eine "Aufgabe zur Zeit ausführen". Vielleicht lohnt es sich, darauf einzugehen.

Wie für den Fortschritt der Berichterstattung kann jede Funktion den Fortschritt beim Start melden (zB "Einloggen" ... "Warten 5 Sekunden um Daten zu bekommen" ... "Daten holen", etc.) Wenn Sie wollen, können Sie Lassen Sie den Timer-Thread die Prioritätswarteschlange regelmäßig durchlaufen und melden Sie, wann bestimmte Aufgaben ausgeführt werden. Obwohl das vielleicht zu viel ist.

Und was Sie gehört haben, ist richtig: Thread.Sleep ist eine außergewöhnlich schlechte Idee, besonders wenn Sie mit Thread-Pool-Threads arbeiten.

    
Jim Mischel 06.11.2011 20:02
quelle
0

Haben Sie darüber nachgedacht, einen Timer (von System.Timers) zu verwenden, um die zeitweiligen "verbleibenden" Nachrichtenupdates durchzuführen? Jede Ihrer Aufgaben könnte einen erwarteten Wert für die Zeit bis zum Abschluss festlegen. Dann könnte Ihre Zeitgeberaufgabe für das Herunterzählen und Aktualisieren der Benutzeroberfläche verantwortlich sein. Kein Thread.Sleep erforderlich, und Timer wird seinen Tick-Code für einen Thread-Pool-Thread ausführen.

    
Dave C 09.11.2011 12:00
quelle

Tags und Links