Search code examples
c#timeouttaskfactory

C# task factory timeout


I have to execute a long process operation in a thread and continue by returning the result to a function. Here is my code :

Task<ProductEventArgs>.Factory.StartNew(() =>
    {
        try
        {
             // long operation which return new ProductEventArgs with a list of product

        }
        catch (Exception e)
        {
            return new ProductEventArgs() { E = e };
        }

    }).ContinueWith((x) => handleResult(x.Result), TaskScheduler.FromCurrentSynchronizationContext());

The problem is actually I don't have a timeout. I want to put a timer in order to return something like this :

   new ProductEventArgs() { E = new Exception("timeout") }; 

if the timeout is reached. Can't use await/async. Thanks a lot !


Solution

  • This code does what you have expressed here:

    var timeout = TimeSpan.FromSeconds(5);
    
    var actualTask = new Task<ProductEventArgs>(() =>
    {
        var longRunningTask = new Task<ProductEventArgs>(() =>
        {
            try
            {
                Thread.Sleep(TimeSpan.FromSeconds(10)); // simulates the long running computation
                return new ProductEventArgs();
            }
            catch (Exception e)
            {
                return new ProductEventArgs() { E = e };
            }
        }, TaskCreationOptions.LongRunning);
    
        longRunningTask.Start();
    
        if (longRunningTask.Wait(timeout)) return longRunningTask.Result;
    
        return new ProductEventArgs() { E = new Exception("timed out") };
    });
    
    actualTask.Start();
    
    actualTask.Wait();
    
    Console.WriteLine("{0}", actualTask.Result.E); // handling E
    

    As you see longRunningTask is created with TaskCreationOptions.LongRunning option. That way it will have a dedicated Thread for it's execution and does not interfere with normal behavior of ThreadPool by occupying a thread from there for too long - which will be needed for other thing like i.e. UI. That's important for long running tasks.

    Note: You could then handle actualTask with ContinueWith but I wanted to express the essence here.