Я создал поток, выполняющий определенный метод. Но иногда я хотел бы убить поток, даже если он все еще работает. Как я могу это сделать? Я попробовал Thread.Abort(), но он обнаружил сообщение с сообщением "Thread aborted". Что мне делать?
Убийство потока .NET
Ответ 1
Не вызывайте Thread.Abort()
!
Thread.Abort
является опасным. Вместо этого вы должны сотрудничать с потоком, чтобы его можно было спокойно отключить. Поток должен быть спроектирован таким образом, чтобы его можно было убить, например, имея флаг boolean keepGoing
, который вы установили в false, когда хотите остановить поток. Тогда поток будет иметь что-то вроде
while (keepGoing)
{
/* Do work. */
}
Если поток может блокироваться в Sleep
или Wait
, тогда вы можете разбить его на эти функции, вызвав Thread.Interrupt()
, Затем нить должна быть готова к обработке ThreadInterruptedException
:
try
{
while (keepGoing)
{
/* Do work. */
}
}
catch (ThreadInterruptedException exception)
{
/* Clean up. */
}
Ответ 2
Вы действительно должны только вызывать Abort() как последнее средство. Вы можете использовать переменную для синхронизации этого потока:
volatile bool shutdown = false;
void RunThread()
{
while (!shutdown)
{
...
}
}
void StopThread()
{
shutdown = true;
}
Это позволяет вашему потоку чисто завершить то, что он делает, оставляя ваше приложение в известном хорошем состоянии.
Ответ 3
Самый правильный и потокобезопасный способ - использовать WaitHandle для подачи сигнала в поток, когда он должен остановиться. В основном я использую ManualResetEvent.
В вашей теме вы можете:
private void RunThread()
{
while(!this.flag.WaitOne(TimeSpan.FromMilliseconds(100)))
{
// ...
}
}
где this.flag
является экземпляром ManualResetEvent. Это означает, что вы можете вызвать this.flag.Set()
извне потока, чтобы остановить цикл.
Метод WaitOne вернет true только тогда, когда установлен флаг. В противном случае он истечет после указанного тайм-аута (100 мс в примере), и поток снова пройдет через цикл.
Ответ 4
Не рекомендуется убивать поток. Лучше сказать, что он должен остановиться и позволить ему закончить изящно. Существуют различные способы сделать это.
- Используйте
Thread.Interrupt
, чтобы вытолкнуть его, если он заблокирован. - Опросите переменную флага.
- Используйте класс
WaitHandle
для отправки сигнала.
Мне не нужно перефразировать, как каждый метод можно использовать, поскольку я уже сделал это в этом ответе.
Ответ 5
Отмена потока - очень плохая идея, так как вы не можете определить, что делал поток во время прерывания.
Вместо этого имейте свойство, которое поток может проверить, и что ваш внешний код может быть установлен. Пусть поток проверяет это логическое свойство, когда он находится в безопасном месте для выхода.
Ответ 6
Я согласен с Джоном Б
volatile bool shutdown = false;
void RunThread()
{
try
{
while (!shutdown)
{
/* Do work. */
}
}
catch (ThreadAbortException exception)
{
/* Clean up. */
}
}
void StopThread()
{
shutdown = true;
}
Ответ 7
Также есть примеры уничтожения потоков в моем классе WebServer...
https://net7ntcip.codeplex.com/SourceControl/changeset/view/89621#1752948
Я бы сказал, что Abort в порядке, просто понять, что такое разветвления... пока вы указываете состояние перед долгой работой Abort будет работать, но нужны флаги, такие как (ShouldStop или ActionBranch и т.д.)
Ознакомьтесь с примерами!