У MSDN в описі методу Thread.Abort () сказано: "Виклик цього методу зазвичай завершує потік".
Чому б НЕ ЗАВЖДИ?
У яких випадках це не припиняє потік?
Чи є якась інша можливість припинення потоків?
У MSDN в описі методу Thread.Abort () сказано: "Виклик цього методу зазвичай завершує потік".
Чому б НЕ ЗАВЖДИ?
У яких випадках це не припиняє потік?
Чи є якась інша можливість припинення потоків?
Відповіді:
Thread.Abort()
вводить a ThreadAbortException
на нитку. Потік може скасувати запит, зателефонувавши Thread.ResetAbort()
. Крім того, існують певні частини коду, наприклад finally
блок, який буде виконаний до обробки винятку. Якщо з якихось причин нитка застряє в такому блоці, виняток ніколи не буде піднятий на потоці.
Оскільки той, хто викликає, дуже мало контролює стан потоку під час виклику Abort()
, як правило, не рекомендується це робити. Натомість передайте повідомлення ланцюжку із запитом на припинення.
У яких випадках це не припиняє потік?
Це питання є дублікатом.
Що поганого у використанні Thread.Abort ()
Чи є якісь інші можливості для припинення потоків?
Так. Ваша проблема полягає в тому, що ви ніколи не повинні запускати нитку, яку ви не можете ввічливо сказати зупинити, і вона зупиняється своєчасно. Якщо у вас ситуація, коли вам доводиться запускати нитку, яку (1) важко зупинити, (2) глючить або найгірше за все (3) вороже ставитись до користувача, тоді правильно зробити новий процес, запустіть потік у новому процесі, а потім завершіть процес, коли ви хочете, щоб потік знизився. Єдине, що може гарантувати безпечне припинення потоку, що не співпрацює, - це операційна система, що видаляє весь процес.
Детальніше див. Мою надмірно довгу відповідь на це запитання:
Використання оператора блокування в циклі в C #
Відповідний біт - це біт у кінці, де я обговорюю міркування щодо того, як довго вам слід чекати, поки потік самовбивство, перш ніж ви його скасуєте.
Чому б НЕ ЗАВЖДИ? У яких випадках це не стосується нитки?
Для початку, потік може зачепити ThreadAbortException
і скасувати власне завершення. Або він може виконати обчислення, яке триває вічно, поки ви намагаєтесь його перервати. Через це час виконання не може гарантувати, що потік завжди закінчується після того, як ви про це попросите.
ThreadAbortException
має більше:
Коли здійснюється виклик методу Abort для знищення потоку, загальновиконавча програма виконує ThreadAbortException. ThreadAbortException - це особливий виняток, який можна перехопити, але він буде автоматично піднятий знову в кінці блоку catch. Коли цей виняток викликаний, час виконання виконує всі нарешті блоки перед закінченням потоку. Оскільки потік може здійснити необмежене обчислення в блоках нарешті або викликати
Thread.ResetAbort()
скасування переривання, немає гарантії, що потік коли-небудь закінчиться.
Вам не потрібно Abort()
вручну обробляти потоки. CLR зробить за вас всю брудну роботу, якщо ви просто дозволите методу в потоці повернутися; що закінчить потік нормально.
Що робити, якщо нитка тримає замок і перервана / вбита? Ресурси залишаються застряглими
Це чудово працює, коли коли потік викликає перервати себе, але не іншим потоком. Перервати, примусово припиняє уражену нитку, навіть якщо вона не виконала своє завдання і не надає можливості для очищення ресурсів
посилання MSDN
подивитися: Найкращі практики керованої потокової роботи
Здається, я не можу перервати нитку, яка застрягла в циклі:
//immortal
Thread th1 = new Thread(() => { while (true) {}});
Однак я можу перервати нитку, якщо вона спить під час циклу:
//mortal
Thread th2 = new Thread(() => { while (true) { Thread.Sleep(1000); }});
ThreadAborts не відбуватиметься всередині блоку нарешті або між BeginCriticalRegion та EndCriticalRegion
ВІД: Щодо всебічного, мовного агностику, сумнівно корисного та смішного сприйняття паралелізму, див. Verity Stob !
У мене були випадки, коли потік був занадто зайнятий, щоб почути виклик Abort (), що зазвичай призводить до того, що ThreadAbortingException перекидається в мій код.