2012-10-23 8 views
6

Ich habe einen Hintergrund Thread, der eine Menge Arbeit macht - Laden der Anwendung. Der Haupt-Thread zeigt den Fortschritt eines UIProgressView an.Wie kann ein Thread feststellen, ob ein anderer Thread abgestürzt ist?

Der Hintergrund-Thread wird mit performSelectorInBackground gelaicht

[self performSelectorInBackground:@selector(loadAppInBackground) withObject:self]; 

Gelegenheiten auf ein paar (obwohl, ich bin nicht auf dieses Verfahren vermählen, wenn ein anderer Ansatz dieses Problem leichter zu lösen macht) einen Fehler verursacht hat, die Hintergrund Thread zum Absturz (verschiedene Bugs, wie die App entwickelt), die dazu führt, dass die Fortschrittsanzeige anhält, aber der Benutzer keine klare Anzeige erhält, dass irgendetwas nicht stimmt.

Ich möchte diese Situation erkennen und scheitern mehr als einfach nur hängen, bis der Benutzer warten aufgibt.

Da die Dauer des Ladevorgangs sehr unterschiedlich sein kann, ist das Timing-Out einfach keine ideale Option.

Was ist der beste Weg für den Vordergrund Thread zu erkennen, dass der Hintergrund Thread ist fehlgeschlagen? Da der Vordergrund-Thread mit der Benutzeroberfläche beschäftigt ist, würde es einen zweiten Hintergrund-Thread erfordern, um den ersten zu überwachen? Das scheint hässlich.

Gibt es einen Thread-zu-Thread-Kommunikationsmechanismus, der verwendet werden könnte, um den Hintergrundprozess zu "pingen"? Besser noch, ein Systemmechanismus auf niedriger Ebene, um den Status anderer Threads zu überprüfen?

Der Debugger kennt alle Threads, die ausgeführt werden ... und scheint ihren Status zu kennen. Ich frage mich, ob es einen Anruf für meine App gibt, um dasselbe zu tun.

+1

Wie versenden Sie diese Hintergrundarbeit (GCD, NSOperations, NSThreads)? Die Antwort hängt von Ihrer Implementierung ab. – CodaFi

+0

[self performSelectorInBackground: @selector (loadAppInBackground) withObject: self]; –

+0

Timeout ist die am häufigsten verwendete Technik. Weil es unmöglich ist festzustellen, ob der Thread normal oder in der Endlosschleife läuft (Halteproblem). Ihr Vordergrund kann also prüfen, ob die Hintergrundaufgabe in 1 Sekunde (lokaler I/O oder 15 ~ 60 Sekunden für Netzwerk-I/O) abgeschlossen wurde. Entschuldigung, ich kann nur einen vagen Vorschlag machen, weil Sie ein generelles Problem stellen. – HKTonyLee

Antwort

0

Es scheint, als ob es keinen Mechanismus in Ziel c gibt, um den Status eines Hintergrund-Threads direkt zu überprüfen. Jede der angebotenen Antworten ist eine gute Wahl ... Entweder kommt es zu Verzögerungen oder der Thread erzeugt eine Art Beweis für seine weitere Existenz.

Ich hatte auf etwas einfacher, zuverlässiger und in Echtzeit gehofft.

Ich werde experimentieren mit dem Abfangen einer Ausnahme im Thread und vielleicht eine Benachrichtigung wie "BackgroundThreadException" erzeugen, auf die der Vordergrund Thread achten und darauf reagieren könnte.

1

Wenn die Hintergrundaufgabe in einem normalen Zyklus ausgeführt wird (z. B. gibt es eine große Schleife, in der ein Großteil der Arbeit erledigt wird), kann sie ab und zu ein Flag setzen, um anzuzeigen, dass sie noch aktiv ist.

Eine Möglichkeit, dies zu tun, ist Hintergrund Thread-Speicher [NSDate timeIntervalSinceReferenceDate] irgendwo zu haben, und in Ihrem Haupt-Thread, gelegentlich (vielleicht auf einen Timer) vergleichen Sie das mit der aktuellen Zeit. Wenn der Unterschied größer als ein vernünftiger Grenzwert ist, können Sie vermuten, dass der Hintergrund-Thread gestorben ist.

Eine andere Möglichkeit ist, dass der Hintergrund-Thread einfach einen Booleschen Wert setzt und der Haupt-Thread dies abfragt und regelmäßig löscht. Wenn der Boolesche Wert zwischen den Hauptthreadabfragen nicht erneut eingestellt wird, können Sie daraus schließen, dass er nicht mehr existiert.

Die erste Technik hat den Vorteil, dass Sie die "vernünftige Grenze" einstellen können, um Code (in jedem Thread) zu tolerieren, der in seinem Timing etwas unregelmäßig ist. Der zweite Ansatz erfordert im Allgemeinen Timings, die besser vorhersagbar sind.

Natürlich wollen Sie bei beiden Ansätzen irgendwie vermeiden, dass "der Pfiff ertönt", wenn der Hintergrundfaden gerade beendet ist und Sie dies noch nicht erkannt haben.

+0

Ja, Plan B verwendet eine Zeitüberschreitung, und wir müssen den gesamten Prozess nicht abbrechen. Jeder einzelne Schritt des gesamten Ladevorgangs kann individuell auslaufen. Ich hatte nur gehofft, dass es einen Anruf gab, dass ich vom Vordergrund aus sicher bestätigen konnte, dass ein anderer Thread noch lief - anstatt zu überprüfen, dass er vor einiger Zeit ausgeführt wurde, indem ich einige Nebeneffekte untersuchte. –

+0

@DaveOwens - Das Problem ist, dass "thread death" allzu oft für immer an einer Sperre hängt oder in einer Art Schleife gefangen wird, oder einfach nicht mehr ausgeführt wird. –

1

Eine gängige Technik ist es, einen zusätzlichen Thread zu haben, um nach Lebenszeichen des betreffenden Threads zu suchen - ein sogenannter Heartbeat-Thread. Der Heartbeat-Thread fragt den Thread ab, indem er überprüft, ob er zeitnah antwortet, wenn nicht, hält er den Thread für tot und beendet ihn. Eine einfache Heartbeat-Thread-Implementierung wäre es, einen Counter zu überprüfen, der regelmäßig vom anderen Thread inkrementiert wird. Wenn der Counter nicht innerhalb einer bestimmten Zeit inkrementiert wird, wird er als tot betrachtet und dann könnte eine entsprechende Aktion wie das Neustarten des Threads ausgeführt werden oder App töten.Ein anderer häufigerer Weg ist, wenn der hb-Thread Nachrichten an den Thread sendet und nach einer Antwort mit einer Zeitüberschreitung sucht.

+0

Ich denke, das würde als absolutes letztes Mittel funktionieren, aber da die Aufgaben das Herunterladen von Dateien unbekannter Größe über Netzwerke unbekannter Geschwindigkeit und Zuverlässigkeit beinhalten, ist es nicht klar, wie viel Zeit bis zum Aufgeben des Hintergrundthreads zu viel Zeit ist tot. –

Verwandte Themen