Intercepting an exception inside IDisposable.Dispose

前端 未结 11 1796
有刺的猬
有刺的猬 2020-12-13 02:07

In the IDisposable.Dispose method is there a way to figure out if an exception is being thrown?

using (MyWrapper wrapper = new MyWrapper())
{
           


        
相关标签:
11条回答
  • 2020-12-13 02:50

    Now, in 2017, this is the generic way to do it, incl handling rollback for exceptions.

        public static T WithinTransaction<T>(this IDbConnection cnn, Func<IDbTransaction, T> fn)
        {
            cnn.Open();
            using (var transaction = cnn.BeginTransaction())
            {
                try
                {
                    T res = fn(transaction);
                    transaction.Commit();
                    return res;
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
                finally
                {
                    cnn.Close();
                }
            }
        }
    

    and you call it like this:

            cnn.WithinTransaction(
                transaction =>
                {
                    var affected = ..sqlcalls..(cnn, ...,  transaction);
                    return affected;
                });
    
    0 讨论(0)
  • 2020-12-13 02:51

    In my case, I wanted to do this to log when an microservice crashes. I already have in place a using to properly clean up right before an instance shut down, but if that's because of an exception I want to see why, and I hate no for an answer.

    Instead of trying to make it work in Dispose(), perhaps make a delegate for the work you need to do, and then wrap your exception-capturing in there. So in my MyWrapper logger, I add a method that takes an Action / Func:

     public void Start(Action<string, string, string> behavior)
         try{
            var string1 = "my queue message";
            var string2 = "some string message";
            var string3 = "some other string yet;"
            behaviour(string1, string2, string3);
         }
         catch(Exception e){
           Console.WriteLine(string.Format("Oops: {0}", e.Message))
         }
     }
    

    To implement:

    using (var wrapper = new MyWrapper())
      {
           wrapper.Start((string1, string2, string3) => 
           {
              Console.WriteLine(string1);
              Console.WriteLine(string2);
              Console.WriteLine(string3);
           }
      }
    

    Depending on what you need to do, this may be too restrictive, but it worked for what I needed.

    0 讨论(0)
  • 2020-12-13 02:52

    It is not only possible to find out if an exception was thrown when a disposable object is disposed you can even get your hands on the exception that was thrown inside the finally clause with a little magic. My Tracing library of the ApiChange tool employs this method to trace exceptions inside a using statement. More infos how this works can be found here.

    Yours, Alois Kraus

    0 讨论(0)
  • 2020-12-13 02:56

    You can extend IDisposable with method Complete and use pattern like that:

    using (MyWrapper wrapper = new MyWrapper())
    {
        throw new Exception("Bad error.");
        wrapper.Complete();
    }
    

    If an exception is thrown inside the using statement Complete will not be called before Dispose.

    If you want to know what exact exception is thrown, then subscribe on AppDomain.CurrentDomain.FirstChanceException event and store last thrown exception in ThreadLocal<Exception> variable.

    Such pattern implemented in TransactionScope class.

    0 讨论(0)
  • 2020-12-13 02:56

    You can do this buy implementing the Dispose method for the "MyWrapper" class. In the dispose method you can check to see if there is an exception as follows

    public void Dispose()
    {
        bool ExceptionOccurred = Marshal.GetExceptionPointers() != IntPtr.Zero
                                 || Marshal.GetExceptionCode() != 0;
        if(ExceptionOccurred)
        {
            System.Diagnostics.Debug.WriteLine("We had an exception");
        }
    }
    
    0 讨论(0)
提交回复
热议问题