Szukam dobrych pomysłów na implementację ogólnego sposobu wykonywania pojedynczego wiersza (lub anonimowego delegata) kodu z przekroczeniem limitu czasu.
TemperamentalClass tc = new TemperamentalClass();
tc.DoSomething(); // normally runs in 30 sec. Want to error at 1 min
Szukam rozwiązania, które będzie można elegancko zaimplementować w wielu miejscach, w których mój kod współdziała z kodem temperamentu (którego nie mogę zmienić).
Ponadto chciałbym, aby naruszający kod „przekroczony limit czasu” przestał być wykonywany dalej, jeśli to możliwe.
c#
multithreading
c#-3.0
asynchronous
timeout
chilltemp
źródło
źródło
Odpowiedzi:
Naprawdę trudną częścią było zabicie długotrwałego zadania poprzez przekazanie wątku wykonawcy z akcji z powrotem do miejsca, w którym można go przerwać. Dokonałem tego za pomocą opakowanego delegata, który przekazuje wątek do zabicia do zmiennej lokalnej w metodzie, która utworzyła lambdę.
Podaję ten przykład dla twojej przyjemności. Metoda, którą naprawdę jesteś zainteresowany, to CallWithTimeout. Spowoduje to anulowanie długotrwałego wątku przez przerwanie go i połknięcie wyjątku ThreadAbortException :
Stosowanie:
Metoda statyczna wykonująca pracę:
źródło
W produkcji intensywnie używamy takiego kodu :
Wdrożenie ma charakter open source, działa wydajnie nawet w równoległych scenariuszach obliczeniowych i jest dostępne w ramach współdzielonych bibliotek Lokad
Ten kod nadal zawiera błędy, możesz spróbować za pomocą tego małego programu testowego:
Jest stan wyścigu. Jest oczywiście możliwe, że wyjątek ThreadAbortException zostanie zgłoszony po
WaitFor<int>.Run()
wywołaniu metody . Nie znalazłem niezawodnego sposobu, aby to naprawić, jednak za pomocą tego samego testu nie mogę powtórzyć żadnego problemu z zaakceptowaną odpowiedzią TheSoftwareJedi .źródło
Cóż, możesz robić rzeczy z delegatami (BeginInvoke, z wywołaniem zwrotnym ustawiającym flagę - i oryginalny kod czekający na tę flagę lub limit czasu) - ale problem polega na tym, że bardzo trudno jest zamknąć działający kod. Na przykład zabijanie (lub wstrzymywanie) wątku jest niebezpieczne ... więc nie sądzę, aby można było to łatwo zrobić solidnie.
Opublikuję to, ale zauważ, że nie jest to idealne rozwiązanie - nie zatrzymuje długotrwałego zadania i nie czyści prawidłowo po niepowodzeniu.
źródło
Kilka drobnych zmian w świetnej odpowiedzi Pop Catalina:
Dodano przeciążenia w celu obsługi sygnalizowania procesu roboczego w celu anulowania wykonania:
źródło
Oto jak bym to zrobił:
źródło
Właśnie to znokautowałem, więc może wymagać poprawy, ale zrobi, co chcesz. Jest to prosta aplikacja na konsolę, ale przedstawia niezbędne zasady.
źródło
A co z użyciem Thread.Join (int timeout)?
źródło