Using TransactionScope to time out regular (non db related) c# code

675 views Asked by At

I am trying to use TransactionScope class to put a specific timeout for code execution. More specifically,

static void Main(string[] args)
    {
        int counter = 0;
        try
        {
            using (var scope = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 5)))                
            {
                for (int i = 0; i < 50000; i++)
                {
                    Console.WriteLine("Counter : {0}", counter);
                    counter++;
                    Thread.Sleep(100);
                }

                scope.Complete();
            }
        }
        catch (Exception ex)
        {

            Console.WriteLine("Exception : {0}", ex);
        }
    }

After some reading about TransactionScope , I would expect the above code block in using statement would be aborted in 5 seconds.

But it does not behave so. The for loop continues to proceed irrespective of transaction timeout (which is what I did not expect). The execution of for loop ends when i = 50000 and I get the below exception after the using statement ends:

Exception : System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.TimeoutException: Transaction Timeout
   --- End of inner exception stack trace ---
   at System.Transactions.TransactionStateAborted.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
   at System.Transactions.CommittableTransaction.Commit()
   at System.Transactions.TransactionScope.InternalDispose()
   at System.Transactions.TransactionScope.Dispose()

Am I doing sth wrong? Is TransactionScope class can only be used for db related code?

What I actualy need is some kind of mechanism that must set a timeout for a block of code execution. I found several links:

How to set timeout for a line of c# code

Set timeout to an operation

Implement C# Generic Timeout

They all seem to execute the timeout requiring code in a seperate thread and abort that thread when timeout occurs. However I think this is messy and I do not want this because of the cost of thread creation and problems of thread abort as explained here :

http://blogs.msmvps.com/peterritchie/2007/08/22/thead-abort-is-a-sign-of-a-poorly-designed-program/

I thought I could use transaction scope to timeout any code block but it does not behave like that.

What is the best solution to put a time limit for a code block execution?

1

There are 1 answers

1
Mikhail On BEST ANSWER

Far as I know, unless the code block is specifically written to know that it can time out (for instance, it's a loop checking the elapsed time and termitating if necessary), there is no way to timeout the operation without aborting the thread. That is messy, as you've pointed out. If the code-block limitations permit this (no state), I would probably start a separate Process (have a pool of them at my disposal, 'cause that's way more expensive than creating threads) to ensure the code block won't affect anything, and run the code there. Kill the process, if the code won't return in time. Down that path, you'll have to come up with a way of invoking the code, assembly resolution, etc. Possibly, use some sandboxing solutions... (Might use AppDomains instead of Processes, but they can bring the host process down if things go South).

I don't think TransactionScope is a good candidate for such a job.