Thread.Sleep成一个任务

时间:2015-12-09 17:17:05

标签: c# .net multithreading task-parallel-library

我有以下代码:

    static void Main(string[] args)
    {
        IEnumerable<int> threadsIds = Enumerable.Range(1, 1000);
        DateTime globalStart = DateTime.Now;

        Console.WriteLine("{0:s.fff} Starting tasks", globalStart);
        Parallel.ForEach(threadsIds, (threadsId) =>
        {
            DateTime taskStart = DateTime.Now;
            const int sleepDuration = 1000;
            Console.WriteLine("{1:s.fff} Starting task {0}, sleeping for {2}", threadsId, taskStart, sleepDuration);
            Thread.Sleep(sleepDuration);
            DateTime taskFinish = DateTime.Now;
            Console.WriteLine("{1:s.fff} Ending task {0}, task duration {2}", threadsId, taskFinish, taskFinish- taskStart);

        });
        DateTime globalFinish= DateTime.Now;
        Console.WriteLine("{0:s.fff} Tasks finished. Total duration: {1}", globalFinish, globalFinish-globalStart);
        Console.ReadLine();
    }

目前,当我运行它时,运行它需要大约60秒。根据我的理解,这是因为.Net不会为每个任务创建一个线程,而是为所有Tasks创建一些线程,当我执行Thread.Sleep时,我会阻止此线程执行其他一些任务。

在我的实际情况中,我有一些工作要并行完成,如果失败,我会等待一段时间才能再次尝试。

我正在查找除Thread.Sleep之外的其他内容,这将允许其他任务在&#34;休眠时间内运行&#34;其他任务。

不幸的是,我目前正在运行.Net 4,这阻止我使用asyncawait(在这种情况下我想这可以帮助我。

Ps,我得到了相同的结果:

  • 推出Task.Delay(sleepDuration).Wait()
  • 不使用Parallel.Foreach,而是使用Task.Factory.StartNew
  • 的foreach

Ps2,我知道我能以不同的方式处理我的真实情况,但我非常乐意了解如何以这种方式实现。

1 个答案:

答案 0 :(得分:-1)

你走在正确的道路上。 Task.Delay(timespan)是解决您问题的方法。由于您无法使用async/await,因此您必须编写更多代码才能获得所需的结果。

考虑使用Task.ContinueWith()方法,例如:

Task.Run(() => { /* code before Thread.Sleep */ })
.ContinueWith(task => Task.Delay(sleepDuration)
    .ContinueWith(task2 => { /* code after Thread.Sleep */ }));

此外,您还需要创建一个类,以便在子任务中访问本地方法变量。

如果您想创建一个将每秒运行一次轮询的任务,您可以尝试以下代码:

Task PollTask(Func<bool> condition)
{
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    PollTaskImpl(tcs, condition);
    return tcs.Task;
}

void PollTaskImpl(TaskCompletionSource<bool> tcs, Func<bool> condition)
{
    if (condition())
        tcs.SetResult(true);
    else
        Task.Delay(1000).ContinueWith(_ => PollTaskImpl(tcs, condition));
}

不要担心每秒创建新任务 - ContinueWithasync/await方法在内部执行相同的操作。