Por que usar o try {} finally {} com um bloco try vazio?

Eu observei em System.Threading.TimerBase.Dipose() o método tem um bloco try{} finally{} mas a try{} está vazia.

Existe algum valor em usar o try{} finally{} com uma tentativa vazia?

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Threading&type=TimerBase

 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal bool Dispose(WaitHandle notifyObject) { bool status = false; bool bLockTaken = false; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { do { if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0) { bLockTaken = true; try { status = DeleteTimerNative(notifyObject.SafeWaitHandle); } finally { m_lock = 0; } } Thread.SpinWait(1); // yield to processor } while (!bLockTaken); GC.SuppressFinalize(this); } return status; } 

De http://blog.somecreativity.com/2008/04/10/the-empty-try-block-mystery/ :

Essa metodologia protege contra uma chamada Thread.Abort interrompendo o processamento. A página MSDN do Thread.Abort diz que “Unexecuted finally blocks são executados antes do thread ser anulado”. Então, para garantir que seu processamento termine mesmo que seu thread seja abortado no meio por alguém chamando Abort em seu thread, você pode colocar todo o seu código no bloco finally (a alternativa é escrever código no bloco “catch” para determine onde você estava antes de “tentar” foi interrompido por Abort e prossiga a partir daí se você quiser.

Isso é para proteger contra Thread.Abort interromper um processo. A documentação para este método diz que:

Unexecuted finally blocks são executados antes do thread ser abortado.

Isso ocorre porque, para recuperar com sucesso de um erro, seu código precisará ser limpo após ele mesmo. Como o C # não possui destruidores no estilo C ++, finally , o using blocos é a única forma confiável de garantir que essa limpeza seja executada de maneira confiável. Lembre-se que using bloco se transforma em isso pelo compilador:

 try { ... } finally { if(obj != null) ((IDisposable)obj).Dispose(); } 

No .NET 1.x, havia uma chance de que finally bloco fosse abortado. Esse comportamento foi alterado no .NET 2.0.

Além disso, os blocos try vazios nunca são otimizados pelo compilador.