Novellizator
Novellizator

Reputation: 14883

How to limit the execution time of a function in c sharp?

I've got a problem. I'm writing a benchmark and I have a function than is either done in 2 seconds or after ~5 minutes(depending on the input data). And I would like to stop that function if it's executed for more than 3 seconds...

How can I do it?

Thanks a lot!

Upvotes: 22

Views: 45862

Answers (9)

gee12
gee12

Reputation: 76

It is possible to execute a function in a separate thread and limit its execution with Thread.Join(millisecondsTimeout):

using System.Threading;

Thread workThread = new Thread(DoFunc);
workThread.Start(param);

if (!workThread.Join(3000))
{
    // DoFunc() took longer than 3 seconds. Thread was aborted
}

private void DoFunc(object param)
{
    // do some long work
}

Upvotes: 2

Amino Trần
Amino Trần

Reputation: 59

private static int LongRunningMethod()
{
    var r = new Random();

    var randomNumber = r.Next(1, 10);

    var delayInMilliseconds = randomNumber * 1000;

    Task.Delay(delayInMilliseconds).Wait();

    return randomNumber;
}

And

var task = Task.Run(() =>
{
    return LongRunningMethod();
});

bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(3000));

if (isCompletedSuccessfully)
{
    return task.Result;
}
else
{
    throw new TimeoutException("The function has taken longer than the maximum time allowed.");
}

it work for me! Source: https://jeremylindsayni.wordpress.com/2016/05/28/how-to-set-a-maximum-time-to-allow-a-c-function-to-run-for/

Upvotes: 5

Maxim V. Pavlov
Maxim V. Pavlov

Reputation: 10509

Since C# and .net framework are not real-time environments, you can't guarantee even the 3 seconds count. Even if you were to get close to that, you would still have to call the

if(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier; before every other call in the method.

All this is just wrong so no, there is just no reliable way to do it from what I know.

Although you can try this solution

https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time

but I just wouldn't do such things in .net application.

Upvotes: -1

shankar_pratap
shankar_pratap

Reputation: 1083

Well..., I had the same question, and after reading all the answers here and the referred blogs, I settled for this,

It Lets me execute any block of code with a time limit, Declare the wrapper method

    public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
    {
        try
        {
            Task task = Task.Factory.StartNew(() => codeBlock());
            task.Wait(timeSpan);
            return task.IsCompleted;
        }
        catch (AggregateException ae)
        {
            throw ae.InnerExceptions[0];
        }   
    }

And use that to wrap any block of code like this

    // code here

    bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(1000), () =>
    {
         //
         // Write your time bounded code here
         // 
    });

    //More code

Upvotes: 66

user2133061
user2133061

Reputation:

The best way in C# to stop function in middle is the return keyword in function, but how do I know when to use the return keyword to stop the function in middle, after it lasts at least 3 seconds? The Stopwatch class from System.Diagnostics is the answer. This complicated function that lasts between 2 seconds to 5 minutes (depending on the input data) logically uses many loops, and maybe even recursion, so my solution for you is that, at the first line code of that function, create an instance of Stopwatch using System.Diagnostics with the new keyword, start it by calling the Start() function of the Stopwatch class, and in for each loop and loop, at the beginning, add the following code:

if (stopwatch.ElapsedMilliseconds >= 3000) { 
     stopwatch.Stop();
     // or 
     stopwatch.Reset(); 
     return;
 } 

(tip: you can type it with hands once, copy it Ctrl+C, and then just paste it Ctrl+V). If that function uses recursion, in order to save memory, make the Stopwatch global instance rather than creating it as local instance at first, and start it if it does not running at the beginning of the code. You can know that with the IsRunning of the Stopwatch class. After that ask if elapsed time is more than 3 seconds, and if yes (true) stop or reset the Stopwatch, and use the return keyword to stop the recursion loop, very good start in function, if your function lasts long time due mainly recursion more than loops. That it is. As you can see, it is very simple, and I tested this solution, and the results showed that it works! Try it yourself!

Upvotes: 5

gjvdkamp
gjvdkamp

Reputation: 10516

You can use the fork/join pattern, in the Task Parallel Library this is implemented with Task.WaitAll()

using System.Threading.Tasks;

void CutoffAfterThreeSeconds() {

    // start function on seperate thread
    CancellationTokenSource cts = new CancellationTokenSource();
    Task loop = Task.Factory.StartNew(() => Loop(cts.Token));

    // wait for max 3 seconds
    if(Task.WaitAll(new Task[]{loop}, 3000)){
       // Loop finished withion 3 seconds
    } else {
       // it did not finish within 3 seconds
       cts.Cancel();           
    }        
}

// this one takes forever
void Loop() {
    while (!ct.IsCancellationRequested) {
        // your loop goes here
    }
    Console.WriteLine("Got Cancelled");
}

This will start the other task on a seperate thread, and then wait for 3000 milliseconds for it to finish. If it did finish within the timeout, it return true, else false so you can use that to decide what to do next.

You can use a CancellationToken to communicate to the other thread that it result is no longer needed so it can stop gracefully.

Regards Gert-Jan

Upvotes: 3

Serge Wautier
Serge Wautier

Reputation: 21878

The best way would be that your function can check its execution time often enough to decide to stop it it takes too long.

If this is not the case, then run the function in a separate thread. In your main thread start a 3 seconds timer. When timer elapses, kill the separate thread using Thread.Abort() (of course unless the function is already over). See sample code and preacuations of usage in the function docs.

Upvotes: 8

Default Writer
Default Writer

Reputation: 2566

Use an OS callbacks with a hi performance counter, then kill your thread, if exists

Upvotes: 0

x2.
x2.

Reputation: 9668

Run this function in thread and kill it after 3 seconds or check elapsed time inside this function(I think it's loop there).

Upvotes: 0

Related Questions