如何暂停任务执行

时间:2012-08-22 20:53:24

标签: c# task-parallel-library

我有这个代码创建一个任务:

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

有时我需要在ExtractStuff

中暂停几秒钟

使用常规Thread.Sleep(1000)可以吗?或者有其他方法可以暂停正在运行的任务吗?

4 个答案:

答案 0 :(得分:3)

Thread.Sleep将阻止运行Task的线程(这不是理想的),但只要你没有运行大量的并行的任务。 .NET 4.5对'async / await'和Task.Delay进行了一些改进,它将隐式设置基于计时器的延续(不需要阻止正在运行的线程),但这不能直接在4.0中使用。

你可以用这样的东西自己做同样的事情(没有经过多少测试,所以谨慎使用):

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");
    }
}

这是相当丑陋的,虽然你可以比上面更好地封装它。它确实消除了“挂起”线程,但是设置延续会产生额外的性能开销。我真的只建议这样做,如果你有很多并行任务在运行,他们都需要引入延迟。

答案 1 :(得分:2)

我认为这样做很好,但最好使用TaskCreationOptions.LongRunning

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

答案 2 :(得分:1)

如果你需要延迟ExtractStuff的执行,你可以看看ThreadPool.RegisterWaitForSingleObject并与一个从未设置的WaitHandle结合。

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);
}

希望这能帮助你完成任务。

答案 3 :(得分:0)

您可以使用Task.Delay(超时)并在ExtractStuff方法中等待它。

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