2

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

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

有时我需要在里面暂停几秒钟ExtractStuff

用普通的可以Thread.Sleep(1000)吗?还是有其他方法可以暂停正在运行的任务?

4

4 回答 4

3

Thread.Sleep 将阻塞运行任务的线程(这并不理想),但只要您不并行运行大量任务,它就可以成为可接受的折衷方案(风险低且对性能没有大问题) . .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");
    }
}

这相当难看,尽管您可以将其封装得比上面的要好一些。它确实消除了“挂起”线程,但是与设置延续相关的额外性能开销。如果你有很多并行任务正在运行并且它们都需要引入延迟,我真的只建议这样做。

于 2012-08-22T21:52:57.563 回答
2

我相信这样做很好,但最好使用TaskCreationOptions.LongRunning

Task.Factory.StartNew(() =>
                    {
                        ExtractStuff(fileName);
                    },TaskCreationOptions.LongRunning);
于 2012-08-22T20:58:54.303 回答
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);
}

希望这对您的探索有所帮助。

于 2012-08-22T21:05:27.987 回答
0

您可以使用 Task.Delay(timeout) 并在您的 ExtractStuff 方法中等待。

private async string ExtractStuff(fileName)
{
   // Your Code
   await Task.Delay(timeout);
}
于 2016-11-29T15:16:31.733 回答