2012-10-23 9 views
6

Mam wątek tła, który wykonuje mnóstwo pracy - ładowanie aplikacji. Główny wątek wyświetla postęp na UIProgressView.W jaki sposób jeden wątek może ustalić, czy inny wątek uległ awarii?

Gwint tło jest zrodził z performSelectorInBackground (choć nie jestem wed tej metody, jeśli inne podejście sprawia, że ​​ten problem łatwiej rozwiązać)

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

na kilku okazjach błąd spowodował tło wątku do awarii (różne błędy w miarę ewolucji aplikacji), co powoduje zatrzymanie paska postępu, ale użytkownik nie otrzymuje wyraźnego wskazania, że ​​coś jest nie tak.

Chciałbym wykryć tę sytuację i zakończyć się niepowodzeniem z większym wdziękiem niż po prostu zawieszeniem, aż użytkownik zrezygnuje z oczekiwania.

Ponieważ czas trwania procesu ładowania może się znacznie różnić, po prostu przekroczenie limitu czasu nie jest rozwiązaniem idealnym.

Jaki jest najlepszy sposób, aby wątek na pierwszym planie wykrył, że wątek tła zawiodł? Ponieważ wątek pierwszoplanowy jest zajęty zajmowaniem się interfejsem użytkownika, czy byłby potrzebny drugi wątek tła do monitorowania pierwszego? To wydaje się brzydkie.

Czy istnieje mechanizm komunikacji wątku z wątkiem, który może być użyty do "pingowania" procesu w tle? Jeszcze lepiej, mechanizm systemu niskiego poziomu sprawdzania statusu innych wątków?

Debugger wie o wszystkich uruchomionych wątkach ... i wydaje się, że zna ich status. Zastanawiam się, czy jest dostępne połączenie z moją aplikacją, aby zrobić to samo.

+1

W jaki sposób wysyłasz tę pracę w tle (GCD, NSOperations, NSThreads)? Odpowiedź zależy od twojej implementacji. – CodaFi

+0

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

+0

Limit czasu jest najczęściej używaną techniką. Ponieważ niemożliwe jest określenie, czy wątek działa normalnie, czy w pętli nieskończoności (problem z zatrzymaniem). Tak więc twój pierwszy plan może sprawdzić, czy zadanie w tle zakończyło się w ciągu 1 sekundy (lokalne operacje we/wy lub 15 ~ 60 s dla operacji we/wy sieci). Przepraszam, mogę podać tylko niejasne sugestie, ponieważ zadajesz ogólny problem. – HKTonyLee

Odpowiedz

0

Wygląda na to, że nie ma mechanizmu w obiektywnym c, aby bezpośrednio sprawdzić status wątku tła. Każda z udzielonych odpowiedzi to przyzwoite opcje ... albo czas oczekiwania, albo posiadanie nici może stanowić dowód na jego dalsze istnienie.

Miałem nadzieję na coś prostszego, bardziej niezawodnego i działającego w czasie rzeczywistym.

Mam zamiar eksperymentować z wyłapaniem wyjątku w wątku i być może wygenerowaniem powiadomienia takiego jak "BackgroundThreadException", którego wątek na pierwszym planie może nasłuchiwać i reagować na nie.

1

Jeśli zadanie w tle działa w pewnym regularnym cyklu (np. Istnieje duża pętla, w której wykonuje się dużo pracy), może ustawić flagę tak często, aby wskazać, że wciąż żyje.

Jednym ze sposobów jest przechowywanie wątku tła [NSDate timeIntervalSinceReferenceDate] gdzieś, aw swoim głównym wątku od czasu do czasu (być może na czasomierzu) należy to porównywać z bieżącym czasem. Jeśli różnica jest większa niż rozsądny limit, możesz zgadnąć, że wątek tła zginął.

Innym sposobem jest ustawienie wątku tła po prostu ustawieniem wartości logicznej, a główny wątek będzie go sprawdzał i czyścił regularnie. Jeśli wartość logiczna nie zostanie ponownie ustawiona między zapytaniami o wątki główne, można wywnioskować, że została ona utracona.

Pierwsza technika ma tę zaletę, że można "dostroić" "rozsądny limit", aby tolerować kod (w obu wątkach), który jest nieco nieregularny w swoim czasie. Drugie podejście zazwyczaj wymaga taktów, które są bardziej przewidywalne.

Oczywiście z jednym podejściem chcesz uniknąć "dmuchania w gwizdek", jeśli wątek tła właśnie się skończył i po prostu jeszcze tego nie rozpoznałeś.

+0

Tak, plan B ma wykorzystywać limit czasu i nie musimy przerywać całego procesu. Każdy indywidualny krok całego procesu ładowania może indywidualnie przerwać. Miałem tylko nadzieję, że było jakieś wołanie, że z pierwszego planu mogę śmiało sprawdzić, czy inny wątek wciąż działa - zamiast sprawdzać, czy działał jakiś czas temu, sprawdzając jakiś efekt uboczny. –

+0

@DaveOwens - Problem polega na tym, że "śmierć wątku" zbyt często zwisa na kłódce lub zostaje złapana w jakąś pętlę, a po prostu przestaje wykonywać. –

1

Powszechnie stosowaną techniką jest posiadanie dodatkowego wątku w celu sprawdzenia oznak życia danego wątku - tzw. Wątku pulsu. Wątek pulsu sonduje wątek, sprawdzając, czy odpowiada on w odpowiednim czasie, jeśli nie, uważa wątek za martwy i kończy go.

Prosta implementacja wątku pulsu będzie polegać na sprawdzaniu licznika, który jest zwiększany regularnie przez inny wątek, jeśli licznik nie zostanie zwiększony w określonym czasie, uznany jest za martwy, a następnie można podjąć odpowiednie działanie, takie jak ponowne uruchomienie wątku lub zabijanie aplikacji.Innym częstszym sposobem jest to, że wątek hb wysyła komunikaty do wątku i sprawdza odpowiedź z przekroczonym limitem czasu.

+0

Przypuszczam, że to działałoby absolutnie w ostateczności, ale ponieważ zadania polegają na pobieraniu plików o nieznanych rozmiarach w sieciach o nieznanej prędkości i niezawodności, nie jest jasne, ile czasu jest zbyt dużo czasu przed poddaniem się i przy założeniu, że wątek tła jest nie żyje. –

Powiązane problemy