The exception is multithreading and Dispose. Why didn’t Dispose call?

Operator

'using' ensures that the Dispose method is called on the object. This does not happen in this example. And the finalizer method did not call either.

Why is all this? And how can I change the code for guaranteed disposal of my objects if exceptions from other threads can occur?

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 in ExceptionExample.Program.ThreadTwo () in \ visual studio 2010 \ Projects \ ExceptionExample \ ExceptionExample \ Program.cs: line 36 in System.Threading.ThreadHelper.ThreadStart_Context (State object) in System. Threading.ExecutionContext.Run (ExecutionContext executeContext, ContextCallback callback, object state, boolean ignoreSyncCtx) in System.Threading.ExecutionContext.Run (ExecutionContext executeContext, ContextCallback callback, object state) in System.Threading.ThreadHelper.

Exclude exception:

\ Visual Studio 2010 \ Projects \ ExceptionExample \ ExceptionExample \ Bin \ Debug> ExceptionExample.exe Block C: \ SomeFodler UnLock C: \ SomeFodler

+3
multithreading c # dispose
Apr 25 2018-11-11T00:
source share
5 answers

An unhandled exception causes the CLR to terminate the process. The disconnect behavior for .NET 4.0 is slightly different, the finalizer starts after the exception message. But not in earlier versions.

You can get around this default behavior by writing an event handler for AppDomain.CurrentDomain.UnhandledException. Record or report the exception and call Environment.Exit (). This allows you to start the finalizer thread and call your Unlock () method.

Do not rely on this; there are unpleasant exceptions, such as StackOverflow or FEEE, which terminate the process anyway. Thus, someone trips over the power cord or removes your process in the head using Taskmgr.exe

+4
Apr 25 '11 at 10:14
source share

Nothing is guaranteed; for example, pulling out the plug or terminating the process will not respect using . All that is guaranteed is that during normal execution (including the most sensible exceptions), it calls Dispose() .

In your case, you have an unhandled thread exception; this is a process killer. All bets are disabled, as your process is currently painful and in the process of suppression (and because of it suffering).

If you want the code to work, you must make sure that you have no exceptions to the process; unhandled exceptions for threads at the top of this list. A try / catch around any thread level code is recommended.

+4
Apr 25 2018-11-11T00:
source share

The reason is because your process terminates due to an unhandled exception, finalizers do not start. See here for more details. You can force your finalizers to work with the trick to complete your process, usually in a processed exception handler from another thread. The policy of the .NET Framework is to do almost nothing when an unhandled exception occurs, because it is not clear what state the process remains. It may not be wise to handle finalizers, because the state of the application may be corrupted, and during finalization, exceptions also occur that will also kill the finalizer thread. The net effect is that only some finalizers were executed, and the rest remained untreated. These subsequent exceptions make it difficult to find the main reason the application failed.

Regards, Alois Kraus

+1
Apr 25 2018-11-11T00:
source share

If you run your threads on BackgroundWorker , then any exceptions made will fall into the worker thread and will be returned as part of the object returned by the thread. This way you do not have to worry about avoiding exceptions.

This creates another problem: you cannot call Join on BackgroundWorker , however you can add Semaphore to the working class class with counter set to 0 (locked):

  private Semaphore workerFinsished = new Semaphore(0, 1); 

add wait after starting your worker,

  public void Join() { workerFinished.WaitOne(); } 

and add Release to your working code where you want to report that you are done.

  workerFinished.Release() 
0
Apr 25 2018-11-11T00:
source share

As Mark said, after your application has unhandled exceptions, all bets are largely disabled. To find out what using does, it takes code like this:

 using(var myDisposableObject = GetDisposableObject()) { // Do stuff with myDisposableObject } 

and translates it into something like this:

 MyDisposableObject myDisposableObject; try { myDisposableObject = GetDisposableObject(); // Do stuff with myDisposableObject } finally { if(myDisposableObject != null) { myDisposableObject.Dispose(); } } 

So what happens when your application encounters an unhandled exception? An unhandled exception terminates the application. This termination (or any unexpected termination) may interfere with the execution of the finally block from your using statement.

You should always handle your exceptions, even if you do not surround your stream calls with try blocks. Consider connecting to the AppDomain.UnhandledException event to clear resources, log files, etc., before your application bites the dust.

EDIT

Just noticed that Hans posted something similar to AppDomain.UnhandledException, and he's right. It was in the case of any program that unexpected endings can give unexpected results. However, in your case, as suggested, do not rely on the complete execution of your application to complete, especially with file resources. Rather, consider writing your own process, to wait, even wait, to fail execution. Then your application can perform incomplete executions if necessary. You can create logs to track progress or mark steps in your process and evaluate them in each run to eliminate abnormal execution states.

Also, as another point, your classes (even considering the fact that they are just samples) are not thread safe ... you are not protecting your shared resources.

0
Apr 25 '11 at 10:16
source share



All Articles