Отмена в .Net является совместной.
Это означает, что тот, у кого есть отмена сигналов CancellationTokenSource
, и тот, у кого есть CancellationToken
, должен проверить, была ли отменена сигнализация (либо путем опроса CancellationToken
или путем регистрации делегата для запуска при его сигнале).
В вашем Task.Run
вы используете параметр CancellationToken
в качестве параметра, но вы не проверяете его внутри самой задачи, поэтому
Чтобы отменить задачу во время ее выполнения, вам нужно проверить CancellationToken
:
var task = Task.Run(() =>
{
token.ThrowIfCancellationRequested();
}, token);
В вашем случае вы блокируете ManualResetEvent
, чтобы вы не смогли проверить CancellationToken
. Вы можете зарегистрировать делегата в CancellationToken
, который освобождает событие сброса:
token.Register(() => waitHandle.Set())
Примечание: Если JVM выходит, в то время как код попытки или выгоды выполняется, то наконец блок не может выполниться. Аналогично, если поток, выполняющий попытку или код выгоды, прерван или уничтожен, наконец, блок не может выполниться даже при том, что приложение в целом продолжается.
я не знаю ни о каких других путях наконец, блок не выполнился бы...
System.exit закрывает Виртуальную машину.
Завершает в настоящее время рабочую виртуальную машину Java. Аргумент служит кодом статуса; условно, ненулевой код статуса указывает на аварийное завершение.
Это вызовы метода
exit
метод в классеRuntime
. Этот метод никогда не возвращается обычно.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"до свидания" не распечатывает в вышеупомянутом коде.
try { for (;;); } finally { System.err.println("?"); }
В этом случае наконец не выполнится (если устаревшее Thread.stop
не называют, или эквивалент, скажем, через интерфейс инструментов).
Только, чтобы подробно остановиться, что сказали другие, что-либо, что не вызывает что-то как выход JVM, подвергнется наконец блок. Так следующий метод:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
странно оба скомпилирует и возвратится 1.
Связанный с System.exit, существуют также определенные типы катастрофического отказа, где наконец блок не может выполниться. Если JVM исчерпывает память полностью, это может просто выйти без выгоды или наконец случая.
А именно, я помню проект, где мы по-дурацки пытались использовать
catch (OutOfMemoryError oome) {
// do stuff
}
, Это не работало, потому что JVM не имела никакой памяти, уехал в выполнение блока выгоды.
Учебник Sun неправильно цитируется здесь в этой ветке.
Примечание. Если JVM завершает работу во время выполнения кода try или catch, то блок finally не будет выполняться . Аналогично, если поток, выполняющий код попытки или улова, прерывается или завершается, блок finally не будет выполняться, даже если приложение в целом продолжает работу.
Если вы внимательно посмотрите на руководство Sun для блока finally, в нем не говорится «не будет выполняться», но «может не выполняться» Вот правильное описание
Примечание: если JVM завершает работу, пока выполняется код попытки или отлова, затем блок finally может не выполняться. Аналогично, если поток, выполняющий код попытки или улова, прерывается или завершается, блок finally может не выполняться, даже если приложение в целом продолжает работу.
Очевидная причина такого поведения заключается в том, что вызов system.exit () обрабатывается в системном потоке времени выполнения, что может занять время для завершения работы jvm, в то время как планировщик потоков может наконец запросить выполнение. Итак, finally разработан так, чтобы всегда выполняться, но если вы закрываете jvm, может случиться так, что jvm отключится до того, как, наконец, будет запущен.