Кажется, что блок 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 http://msdn.microsoft.com /en-us/library/system.threading.threadabortexception.aspx
При вызове метода Abort для уничтожения потока общеязыковая среда выполнения создает исключение ThreadAbortException. ThreadAbortException — это особое исключение, которое можно перехватить, но будет автоматически поднят снова в конце блока catch. Когда возникает это исключение, среда выполнения выполняет все блоки 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 создается в потоке, который изначально под названием «Выгрузить».Если поток, который не может быть прерван в конце концов заканчивается, целевой домен не выгружается. Таким образом, в .NET Framework домен версии 2.0 не гарантированно выгружается, потому что он может не можно завершить выполнение потоков.
Заключение. В некоторых случаях мне нужно подумать, будет ли мой код выполняться в фоновом или переднем потоке? Возможно ли, что мой код не будет завершен до того, как основной поток приложения завершит всю работу?