Кажется, что блок finally не выполняется, если он отличается от кода выполнения основного потока. Возможно ли принудительное выполнение в этом случае?
Среда: VS 2010, .Net Framework 4.0.3
class Program
{
static void Main(string[] args)
{
var h = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(
obj => TestProc(h));
h.WaitOne();
}
private static void TestProc(EventWaitHandle h)
{
try
{
Trace.WriteLine("Try");
h.Set();
}
catch(Exception)
{
Trace.WriteLine("Catch");
}
finally
{
Thread.Sleep(2000);
Trace.WriteLine("Finally");
}
}
}
Обновление:
Я нашел упоминания и объяснения по этому делу в MSDN:
ThreadAbortException Class
http://msdn.microsoft.com/en-us/library/system.threading.threadabortexception.aspx
Когда вызывается метод Abort для уничтожения потока,
общеязыковая среда выполнения выдает исключение ThreadAbortException.
ThreadAbortException - это особое исключение, которое может быть перехвачено, но оно
будет автоматически поднят снова в конце блока захвата. когда
это исключение возникает, среда выполнения выполняет все блоки finally
до окончания потока . Потому что поток может делать неограниченное
вычисление в блоках finally или вызов Thread.ResetAbort для отмены
прерывание, нет никакой гарантии, что поток когда-либо закончится . Если
Вы хотите подождать, пока прерванный поток не закончится, вы можете вызвать
Thread.Join метод. Присоединение - это блокирующий вызов, который не возвращается до
поток фактически останавливается.
Примечание:
Когда общеязыковая среда выполнения (CLR) останавливает фоновые потоки после
все потоки переднего плана в управляемом исполняемом файле закончились, это не
использовать Thread.Abort. Следовательно, вы не можете использовать ThreadAbortException для
определить, когда фоновые потоки завершаются CLR.
Темы переднего плана и фона http://msdn.microsoft.com/en-us/library/h339syd0.aspx
Когда среда выполнения останавливает фоновый поток из-за завершения процесса, исключение не генерируется в потоке. Однако, когда потоки останавливаются из-за того, что метод AppDomain.Unload выгружает домен приложения, ThreadAbortException генерируется как в основном, так и в фоновом потоках.
Так почему же в конце приложения CLR не использует метод AppDomain.Unload для выгрузки домена приложения до завершения (уничтожения) основного процесса?
Потому что http://msdn.microsoft.com/en-us/library/system.appdomain.unload.aspx:
Когда поток вызывает Unload, целевой домен помечается для выгрузки.
Выделенный поток пытается выгрузить домен и все потоки в
домен прерван. Если поток не прерывается, например
потому что он выполняет неуправляемый код, или потому что он выполняет
наконец, блок, затем через некоторое время
CannotUnloadAppDomainException выбрасывается в поток, который первоначально
называется Unload. Если поток, который не может быть прерван в конце концов
заканчивается, целевой домен не выгружается. Таким образом, в .NET Framework
домен версии 2.0 не гарантированно выгружает , потому что он может не
можно прекратить выполнение потоков.
Вывод: в некоторых случаях мне нужно подумать, будет ли мой код выполняться в фоновом или переднем потоке? Возможно ли, что мой код не будет завершен, пока основной поток приложения не завершит всю работу?