Почему код в блоке finally не не казнить?

Кажется, что блок 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 не гарантированно выгружается, потому что он может не можно завершить выполнение потоков.

Заключение. В некоторых случаях мне нужно подумать, будет ли мой код выполняться в фоновом или переднем потоке? Возможно ли, что мой код не будет завершен до того, как основной поток приложения завершит всю работу?

8
задан Andir 13 March 2012 в 18:19
поделиться