2

Note: I am restricted to .net 4.0

I am currently using stopwatch to measure the time it takes for an action to run. After the action completes, I do logic based on the time. More specificaly, I check if the time went beyond a certain threshold.

I recently discovered the Task.Wait(int timeout) method

Is it better to put my action in a task and wait for it on my threshold?

for example:

bool isOnTime=false;
Task action = new Task(() => someMethod());
action.Start();
isOnTime = action.Wait(myThreshold);

if(!isOnTime)
{
...some code
}

Edit: Updating the question since everyone thinks i want to run a task

This is how i currently do it:

Stopwatch watch = Stopwatch.StartNew();
someMethod();
watch.Stop();
executeTime = watch.ElapsedMilliseconds;

later i am running:

if (executeTime > Threshold)

I am running the method synchronously and i want to keep it that way

Enfantcool
  • 221
  • 1
  • 6

4 Answers4

1

What happens now is that if the action takes longer than myThreshold, the action will be cancelled. I don't think that is what you want. Besides that, you are also blocking the calling thread by using .Wait().

I'd say stick to the stopwatch or think of something else.

Edit: my bad, my understanding of Task.Wait() is not correct. I learned something today, so that's good :-)

Still, unless someMethod is an async method, you are using another thread. So if concurrency is not a problem, it would be a nice option.

user6385193
  • 53
  • 1
  • 8
Peter Bons
  • 26,826
  • 4
  • 50
  • 74
  • 1
    Task.Wait(int timeout) does not cancel the task. It cancels the Wait after the timeout – Enfantcool May 30 '16 at 13:11
  • It's in general not possible to cancel any .NET code without the code cooperating. This is important to realize. – usr May 30 '16 at 13:25
1

It is fine if the action runs for longer than my threshold

It seems what you want to run it asynchronously, then Task.Wait is more appropriate as you get information about timeout as soon as happens (while method may still run longer).

You can use wrapper method to run similar to

bool IsCompletedInTime(Action action, int msTimeout) =>
    Task.Run(() => action()).Wait(msTimeout);

Usage:

if(!IsCompletedInTime(someMethod, myThreshold))
{
    ... // timeout
}
Sinatr
  • 20,892
  • 15
  • 90
  • 319
1

This is a reasonable approach. You can abandon the task after a timeout.

The problem with that is that the task might consume resources or cause side effects after the timeout. It's generally better to implement a cancellation scheme and cancel the task:

var cts = new CTS();
var task = Task.Run(() => F(cts.Token));
cts.CancelAfter(...);
task.Wait();

Here, we are always waiting on the task to ensure that it is shut down. It's the responsibility of F to ensure timely cancellation.

That way we can avoid all concurrency issues caused by a possibly rogue task.

usr
  • 168,620
  • 35
  • 240
  • 369
0

Perhaps you should avoid blocking by using a continuation to handle how long the task took to complete.

For example:

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            Stopwatch sw = new Stopwatch();

            var task = new Task(() => 
            {
                sw.Start();
                someMethod();
            });

            task.Start();

            task.ContinueWith(antecedent => 
            {
                if (sw.ElapsedMilliseconds >= 1000 )
                    Console.WriteLine("Took at least second.");
                else
                    Console.WriteLine("Took less than a second.");
            });

            Console.WriteLine("Press <ENTER> to exit.");
            Console.ReadLine();
        }

        static void someMethod()
        {
            Thread.Sleep(2000);
        }
    }
}

Then you won't be blocking any tasks while waiting for the task to complete.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Do not use Thread.Sleep if you are working with tasks, use the delay method if .net4.5, otherwise http://stackoverflow.com/questions/15341962/how-to-put-a-task-to-sleep-or-delay-in-c-sharp-4-0 – Enfantcool May 30 '16 at 14:08
  • @Enfantcool This is just something to simulate the thread taking some time; it's completely unnecessary to use Thread.Delay() in this context. In any case, look at the top row of the OP: **Note: I am restricted to .net 4.0** – Matthew Watson May 30 '16 at 14:16
  • @Enfantcool I have rejected your edit; it's not really appropriate for this answer. The contents of `someMethod()` is immaterial other than it must take longer than a second to return - the point is to show that you can use `.ContinueWith()` to achieve what you want. – Matthew Watson May 30 '16 at 14:27
  • You are running the task asynchronously in your answer. Tasks do not guarantee a separate thread. You could be putting the main thread to sleep if you use Thread.Sleep(2000); The point is if i took your code and copy pasted it, it wouldn't work. – Enfantcool May 30 '16 at 14:32
  • @Enfantcool It works in the Console application in this answer because the default TaskScheduler will create a new thread.The contents of `someMethod()` that you will be using will of course be the one in your code rather than the code here, so it wouldn't contain the `Thread.Sleep()`. You're focusing on the wrong thing - the point to take away is that you can use `Task.ContinueWith()` to solve the issue. You certainly wouldn't be copy/pasting the contents of `someMethod()` into your actual code, would you? – Matthew Watson May 30 '16 at 15:00