HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Time Limit decorator

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
decoratorlimittime

Problem

I have an interface named ICodeRunner, defined like this:

public interface ICodeRunner
{
ExecutionResult Run(string code);
}


I have more classes that implement ICodeRunner, but regardless of which one is used, in some contexts only I have to impose a time limit on the execution of the Run method. This is a regular timeout: "if it's not done in x seconds, throw an exception."

To achieve this, I have created a class called CodeRunnerTimeLimitDecorator that can wrap any class implementing ICodeRunner and provide this functionality.

This is how the class is implemented:

public class CodeRunnerTimeLimitDecorator : ICodeRunner
{
private readonly ICodeRunner _wrapped;
private readonly int _timeoutInSeconds;

public CodeRunnerTimeLimitDecorator(ICodeRunner wrapped, int timeoutInSeconds)
{
_wrapped = wrapped;
_timeoutInSeconds = timeoutInSeconds;
}

public ExecutionResult Run(string code)
{
var executionResult = new ExecutionResult();

var t = new Thread(() => executionResult = _wrapped.Run(code));

t.Start();

var completed = t.Join(_timeoutInSeconds * 1000);

if (completed)
return executionResult;

throw new ApplicationException(
string.Format("Code took longer than {0} seconds to run, so it was aborted.", _timeoutInSeconds));
}
}


While I welcome any advice about how to make this code better, I'm particularly interested in comments/improvements regarding the time limit mechanism.

Update:

More specifically, the questions are:

-
Is there an easier/cleaner way to do it?

-
Would it be OK if I called t.Abort() in case the timeout had elapsed*?

*I do not control the process that goes on inside _wrapped.Run(code), so I cannot implement Task Cancellation or similar techniques.

Solution

This is actually a stab in the dark but could you use the .NET 4 System.Threading.Task object for this. Something like:

var task = Task.Factory.StartNew(() => _wrapped.Run(code) });

// Wait returns true if the task finished within the allocated timeframe
// http://msdn.microsoft.com/en-us/library/dd270644.aspx
if(task.Wait(_timeoutInSeconds * 1000))
{
   return executionResult;
}
else
{
   throw new ApplicationException(string.Format("Code took longer than {0} seconds to run, so it was aborted.", _timeoutInSeconds));
}

Code Snippets

var task = Task.Factory.StartNew(() => _wrapped.Run(code) });

// Wait returns true if the task finished within the allocated timeframe
// http://msdn.microsoft.com/en-us/library/dd270644.aspx
if(task.Wait(_timeoutInSeconds * 1000))
{
   return executionResult;
}
else
{
   throw new ApplicationException(string.Format("Code took longer than {0} seconds to run, so it was aborted.", _timeoutInSeconds));
}

Context

StackExchange Code Review Q#12321, answer score: 3

Revisions (0)

No revisions yet.