Writing code to run the last method to throw exceptions in a multithreaded web application

I wrote several try-catch blocks for various methods today, and I thought it would be nice to have a utility method that automatically calls the method again for the multiple times given in the parameter at a specific time.

However, I thought to myself: the method / property etc. that would throw the exception would be at the top of the stacktrace (are property calls being received on the stack?) In a single threaded application (so an application without thread related code). So I can just get the method name at the top and call it dynamically again.

So, I would have code like:

string s = StackTrace.GetFrame (0) .GetMethodName; (I can't remember the exact syntax).

With this method, I can accomplish it with an activator or one of several ways.

But in a multi-threaded application, I could run multiple methods at once and I don't know which one ends up first / last. Therefore, I cannot expect the method I am writing the try-catch block for to be at the top of the stack.

How can I achieve this?

0


source to share


3 answers


Please, do not do that. It's a really, really, really, really, really, really bad idea.



Maybe not as bad as deleting files randomly if your hard drive is low on space - but about as bad.

+4


source


While I doubt the need for an automatic retry mechanism (random retry will really help you in so many situations where you need a utility method?) - using StackTrace and Reflection is, at best, a terribly complex solution.

Not that I am suggesting that anyone actually use this code, but I would probably go with a delegate based approach to this particular problem:

public static class Extensions {
    public static void Try(this Action a, int maxTries) {
       new (Func<bool>(() => { a(); return true; })).Try(maxTries);
    }

    public static TResult Try<TResult>(this Func<TResult> f, int maxTries) {
       Exception lastException = null;

       for (int i = 0; i < maxTries; i++) {
          try {
              return f();
          } catch (Exception ex) {
              lastException = ex;
          }
       }

       throw lastException;
    }
}

      

The usage is a bit unorthodox but pretty clear:

// Set a property
new Action(() => myObject.Property = 5).Try(5);

// With a return value
var count = new Func<int>(() => myList.Count).Try(3);

      



You can't embed lambda in a method, but you can have a somewhat fluent interface:

Utilities.Try(
   () => MyObject.Property = 5
).Repeat(5);

      

And multi-line methods:

Utilities.Try(() => {
   MyObject.Property1 = 5;
   MyObject.Property2 = 6;
   MyObject.Property3 = 7;
}).Repeat(5);

      

+1


source


Mark code is probably better, but here is mine ...

If you really want to do something like this, I would use code something like this. Yes, you still have to manually call it, but your idea of โ€‹โ€‹indiscriminately repeating EVERYTHING except methods is really a very bad idea.

public class TryAgain
{
    public delegate void CodeToTryAgain ();

    public static void Repeat<E>(int count, CodeToTryAgain code) where E : Exception
    {
        while (count-- > 0)
        {
            try
            {
                code();
                return;
            }
            catch (E ex)
            {
                Console.WriteLine("Caught an {0} : {1}", typeof(E).Name, ex.Message);
                // ignoring it!
            }
        }
    }
}

      

And then you call your opt-out method, ThrowTwice

or whatever you want to do, for example:

TryAgain.Repeat<MyException>(5, delegate()
{
    ThrowTwice();
});

      

In this example, the Repeat method will ignore all MyExceptions by trying to call ThrowTwice up to 5 times ...

You can add your own sleeping and timeouts and whatever.

0


source







All Articles