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

Odpowiedz Nowy wątek
Anonymus
2011-06-02 19:51
Anonymus
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.

Pozostało 580 znaków

2011-06-02 20:52

Rejestracja: 15 lat temu

Ostatnio: 4 godziny temu

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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2011-06-02 21:19

Rejestracja: 9 lat temu

Ostatnio: 8 lat temu

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

Pozostało 580 znaków

Rev
2011-06-02 21:21
Rev
Moderator

Rejestracja: 13 lat temu

Ostatnio: 1 tydzień temu

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.


Pozostało 580 znaków

2011-06-02 21:26

Rejestracja: 9 lat temu

Ostatnio: 8 lat temu

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.

Pozostało 580 znaków

2011-06-02 21:34
Moderator

Rejestracja: 12 lat temu

Ostatnio: 14 minut temu

Lokalizacja: Wrocław

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.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

Rev
2011-06-02 21:35
Rev
Moderator

Rejestracja: 13 lat temu

Ostatnio: 1 tydzień temu

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).


Pozostało 580 znaków

2011-06-02 21:58

Rejestracja: 9 lat temu

Ostatnio: 8 lat temu

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ł.

edytowany 1x, ostatnio: gawronlukasz, 2011-06-02 22:01

Pozostało 580 znaków

Anonymus
2011-06-02 23:35
Anonymus
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? :)

Pozostało 580 znaków

2011-06-03 00:35
Moderator

Rejestracja: 12 lat temu

Ostatnio: 14 minut temu

Lokalizacja: Wrocław

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/senth[...]-dangers-of-thread-abort.aspx
http://www.albahari.com/threa[...]rt3.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ś.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
edytowany 1x, ostatnio: somekind, 2011-06-03 00:36

Pozostało 580 znaków

Anonymus
2011-06-03 01:08
Anonymus
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...

Pozostało 580 znaków

Odpowiedz

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