Multithreading exception and Dispose. Why Dispose didn't call?
c#, dispose, multithreading
Solution
The unhandled exception forces the CLR to terminate the process. Shutdown behavior is slightly different for .NET 4.0, the finalizer will run after reporting the exception. But not in earlier versions.
You can work around this default behavior by writing an event handler for AppDomain.CurrentDomain.UnhandledException. Log or report the exception and call Environment.Exit(). That allows the finalizer thread to run and call your Unlock() method.
Do not rely on this, there are nasty exceptions like StackOverflow or FEEE that terminate the process anyway. So does somebody tripping over the power cord or shooting your process in the head with Taskmgr.exe
Problem
'using' statement guaranteed that for the object will be called Dispose method. In this example this is not happening. And finalizer method didn't call too. Why all this? And how I can change code for guaranteed disposing of my objects when exceptions on other threads can happens? ``` class Program { static void Main(string[] args) { Thread th1 = new Thread(ThreadOne); Thread th2 = new Thread(ThreadTwo); th1.Start(); th2.Start(); th1.Join(); th2.Join(); } static void ThreadOne() { using (LockedFolder lf = new LockedFolder(@"C:\SomeFodler")) { // some pay load Thread.Sleep(5000); } } static void ThreadTwo() { // some pay load Thread.Sleep(1000); throw new Exception("Unexpected exception"); } } public class LockedFolder : IDisposable { private const string FILENAME_LOCK = ".lock-file"; private bool bLocked = false; public string FullPath { private set; get; } public LockedFolder(string FullPath) { this.FullPath = FullPath; Lock(); } private void Lock() { // lock our folder Console.WriteLine("Lock " + FullPath); //CreateLockFile(Path + FILENAME_LOCK); bLocked = true; } private void UnLock() { if (!bLocked) { Console.WriteLine("Already UnLocked " + FullPath); return; // already unlocked } Console.WriteLine("UnLock " + FullPath); // unlock our folder //DeleteLockFile(Path + FILENAME_LOCK); bLocked = false; } #region IDisposable Members private bool disposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void Dispose(bool disposing) { if (!disposed) { if (disposing) { // Free managed resources } // Free unmanaged resource UnLock(); } disposed = true; } ~LockedFolder() { Dispose(false); } #endregion } ``` Output: \Visual Studio 2010\Projects\ExceptionExample\ExceptionExample\bin\Debug>ExceptionExample.exe Lock C:\SomeFodler Unhandled Exception: System.Exception: Unexpected exception at ExceptionExample.Program.ThreadTwo() in \visual studio 2010\Projects\ExceptionExample\ExceptionExample\Program.cs:line 36 at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() Outupt without exception: \Visual Studio 2010\Projects\ExceptionExample\ExceptionExample\bin\Debug>ExceptionExample.exe Lock C:\SomeFodler UnLock C:\SomeFodler