Jak prawidłowo zakończyć wątek z innego wątku?

0

Szukam i szukam... Jak prawidłowo zakończyć wątek z innego wątku? Dajmy na to że mam wątek:

Thread duzoPracy = new Thread(mojaMetoda);
Thread.Start()

Wywołanie z głównego wątku aplikacji:

duzoPracy.Abort()

nie daje efektu, ponieważ wątek jest zajęty...
Próbowałem też umieścić w mojaMetoda:

if(Thread.CurrentThread.ThreadState == ThreadState.RequestAbort)
     return;

Ale też nie działa...
Jak prawidłowo zakończyć wątek z innego wątku? MSDN twierdzi tylko że Abortem mogę próbować, a i tak nie mogę mieć pewności że się uda, czyli pogadane... Proszę o pomoc.

0

Stwórz jakąś flagę, widoczną i dla wątku głównego i dla nowo utworzonego wątku. Ewentualnie, np w Javie jest funkcja Thread.isInterrupted(), Thread.interrupt() itd, które właśnie służą do obsługi takiej wewnętrznej flagi. W C# powinno być coś podobnego. Być może ten Abort właśnie. Pracę musisz podzielić na kawałki, jeden kawałek to jeden obieg pętli, przy każdym obiegu pętli sprawdzaj stan wątku.

0

Jeśli masz coś takiego:

private void Funkcja()
{
   try
   {
     //jakas operacja
   }
   catch(ThreadAbortException)
   {
      //jakas obsluga przerwania watku
   }
}

Thread watek = new Thread(Funkcja);
watek.Start();
 

to jeśli później w kodzie innego wątku robisz watek.Abort() to blok "jakas operacja" zostaje przerwany rzuceniem wyjątku ThreadAbortException, czy takie coś Ci nie działa? Postaw sobie Breakpointa w bloku:

catch(ThreadAbortException)
{
}
 

i sprawdź czy jest rzucany.

Pozdrawiam
Łukasz Gawron

0

Ta zaproponowana opcja nie jest zła, tylko ma jeden minus. Jak odpalisz w nim jakąś blokującą funkcję z P/Invoke to wyjątek zostanie zgłoszony dopiero PO skończeniu wywołania tej funkcji.

0

Owszem, ale czy to coś zmienia? Jeśli chcesz mieć potwierdzenie zakończenia to możesz np. rzucić eventa WatekAborted z bloku catch kiedy watek faktycznie jest przerwany.

0

Można też zresetować komputer. To nawet lepsze rozwiązanie, bo wątek zostanie na pewno przerwany i nie zablokuje przy okazji żadnych zasobów.

0

Owszem. Jak masz tam GetMessage, a wątek nie otrzyma do końca życia aplikacji żadnej wiadomości to dostajesz memory leak. Powiesz, że zawsze można wątkowi wysłać jakąś wiadomość - no cóż, Microsoft uznał, że wątek w .NET może zostać zaimplementowany na różne sposoby i od pewnego czasu nie oferują możliwości uzyskania natywnego id (no, w praktyce istnieje prywatne pole o nazwie "DONT_USE_InternalThread", ale jego nazwa mówi sama za siebie).

0

W takim razie lepiej nie używać tego typu funkcji we wątku, który planujesz przerywać :p albo pogodzić się z możliwością memory leaka i najlepiej wtedy wątku nie ustawiać jako :

Thread watek = new Thread(funkcja);
watek.IsBackground = false;
 

żeby przynajmniej główny proces mógł się zakończyć, kiedy będziesz tego chciał.

0

Bardzo dziękuję za odpowiedzi.
Zrobiłem flagę i co gorsze... działa. Nasuwa się pytanie, jakim prawem działa. Przecież ja ją zmieniam z głównego wątku aplikacji(czyli innego niż 'duzoPracy'), nie powinno wywalić exceptiona?

Druga rzecz, gdy zmienię flagę, i pętla która jedzie w wątku sprawdzi, że powinna kończyć, i zakończy, to... Wynik na oknie i tak mam taki jak bym nie dał końca, a mimo to, wątek kończy się natychmiastowo. Stworzyłem swego rodzaju perpetummobile. Jakiś pomysł na to? :)

0

Prosiłbym osobę, która zminusowała mojego posta, o zagwarantowanie, że BRUTALNIE PRZERWANY WĄTEK zwolni wszystkie swoje zasoby i nie spowoduje żadnych dziwnych zachowań ani niestabilności aplikacji.

http://msmvps.com/blogs/senthil/archive/2008/12/17/the-dangers-of-thread-abort.aspx
http://www.albahari.com/threading/part3.aspx#_Interrupt_and_Abort

Anonymus napisał(a)

Zrobiłem flagę i co gorsze... działa. Nasuwa się pytanie, jakim prawem działa. Przecież ja ją zmieniam z głównego wątku aplikacji(czyli innego niż 'duzoPracy'), nie powinno wywalić exceptiona?

Dlaczego uważasz, że powinno?

Druga rzecz, gdy zmienię flagę, i pętla która jedzie w wątku sprawdzi, że powinna kończyć, i zakończy, to... Wynik na oknie i tak mam taki jak bym nie dał końca, a mimo to, wątek kończy się natychmiastowo. Stworzyłem swego rodzaju perpetummobile. Jakiś pomysł na to? :)

Bez kodu trudno powiedzieć, co zepsułeś.

0

Dlaczego uważasz, że powinno?

Bo przecież gdy z innego wątku(nie głównego) próbujemy np. zmienić wartość progress bara to dostajemy wyjątek. Nie przypadkiem dlatego że odwołujemy się do zmiennej z innego wątku? Czegoś tu nie rozumiem. Dzięki za poświęcony czas...

0
Anonymus napisał(a)

Bo przecież gdy z innego wątku(nie głównego) próbujemy np. zmienić wartość progress bara to dostajemy wyjątek. Nie przypadkiem dlatego że odwołujemy się do zmiennej z innego wątku? Czegoś tu nie rozumiem. Dzięki za poświęcony czas...

Dlatego, że odwołujemy się do kontrolki z wątku GUI. Normalne odwoływanie się do zmiennych z innych wątków nie jest zakazane, trzeba tylko użyć jakichś locków albo semaforów do synchronizacji takich operacji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1