user1615362
user1615362

Reputation: 3817

How to pause task execution

I have this code that creates a task:

 Task.Factory.StartNew(() =>
                        {
                            ExtractStuff(fileName);
                        });

Sometimes I need to pause for few seconds inside ExtractStuff

Is it OK to use the regular Thread.Sleep(1000)? Or is there another way to pause the running task?

Upvotes: 3

Views: 12651

Answers (4)

Lee Dale
Lee Dale

Reputation: 1196

You could use Task.Delay(timeout) and await that inside your ExtractStuff method.

private async string ExtractStuff(fileName)
{
   // Your Code
   await Task.Delay(timeout);
}

Upvotes: 0

Dan Bryant
Dan Bryant

Reputation: 27515

Thread.Sleep will block the thread running the Task (which is not ideal), but it can be an acceptable compromise (low risk and not a huge problem to performance) as long as you're not running a large number of tasks in parallel. .NET 4.5 has some improvements with 'async/await' and Task.Delay that will implicitly set up a continuation based on a timer (which doesn't require blocking a running thread), but this is not directly available in 4.0.

You can do the same thing yourself with something like this (not tested much, so use with caution):

class Program
{
    static void Main(string[] args)
    {
        var fullAction = RunActionsWithDelay(DoSomething, 2000, DoSomethingElse);
        fullAction.Wait();
        Console.WriteLine("Done");
        Console.ReadLine();
    }

    static Task RunActionsWithDelay(Action first, int delay, Action second)
    {
        var delayedCompletion = new TaskCompletionSource<object>();
        var task = Task.Factory.StartNew(DoSomething);
        task.ContinueWith(t =>
        {
            if (t.IsFaulted)
            {
                delayedCompletion.SetException(t.Exception);
            }
            else
            {
                Timer timer = null;
                timer = new Timer(s =>
                {
                    try
                    {
                        DoSomethingElse();
                        delayedCompletion.SetResult(null);
                    }
                    catch (Exception ex)
                    {
                        delayedCompletion.SetException(ex);
                    }
                    finally
                    {
                        timer.Dispose();
                    }
                }, null, delay, Timeout.Infinite);                    
            }

        });
        return delayedCompletion.Task;
    }

    static void DoSomething()
    {
        Console.WriteLine("Something");
    }

    static void DoSomethingElse()
    {
        Console.WriteLine("Something Else");
    }
}

This is fairly ugly, though you can encapsulate it a bit better than the above. It does eliminate the 'hanging' thread, but there is additional performance overhead associated with setting up the continuations. I really only recommend doing this if you have a lot of parallel tasks running and they all need to introduce delays.

Upvotes: 3

Casperah
Casperah

Reputation: 4554

If you need to delay the execution of ExtractStuff you can take a look at ThreadPool.RegisterWaitForSingleObject and combine with an WaitHandle that is never set.

private static WaitHandle NeverSet = new WaitHandle();
private void ExtractStuff(object state)
{
    string filename = state as string;
    ....
}

private void StartExtract(string filename);
{
    ThreadPool.RegisterWaitForSingleObject(NeverSet, ExtractStuff, fileName, seconds * 1000, true);
}

Hope that this will help you in your quest.

Upvotes: 1

PMC
PMC

Reputation: 4766

I believe it is fine to do this but preferable to use TaskCreationOptions.LongRunning.

Task.Factory.StartNew(() =>
                    {
                        ExtractStuff(fileName);
                    },TaskCreationOptions.LongRunning);

Upvotes: 2

Related Questions