为什么Task.Delay()允许无限延迟?

时间:2012-05-24 16:13:06

标签: .net .net-4.0 task-parallel-library .net-4.5 async-await

在我的应用程序冻结之后,我将原因跟踪到等待Task.Delay()(或.NET 4.0中的TaskEx.Delay())创建的任务的线程,它为其提供了计算TimeSpan由于某个错误,有时会计算TimeSpan TotalMilliseconds小于或等于-1且大于-2(即-10000到-1之间) -19999蜱,包括在内。

当您传递TimeSpan毫秒或更低的负-2时,该方法会正确抛出ArgumentOutOfRangeException,但是当您从上述范围提供负TimeSpan时,它返回一个永不完成的Task(通过将基础System.Threading.Timer设置为-1表示无穷大的dueTime。这意味着在该任务上设置的任何延续都将永远不会执行,并且.Wait()Task上发生的任何不良线程将永远被阻止。

从未完成的Task有什么可能的用途?有人会期望这样的回报值吗?不应将任何负值传递给.Delay(),包括该特殊范围内的值,抛出ArgumentOutOfRangeException

3 个答案:

答案 0 :(得分:9)

当你想无限期地等待一个长时间运行的任务时,

Timeout.Infinite或-1非常有用,这个任务将花费不确定的时间来完成,但最终会完成。

Win32 API还使用常量INFINITE = -1进行无限超时。

您通常不希望在UI线程中使用它,因为它可能会冻结UI(这似乎是您的问题)。但是在工作线程中存在有效的用例 - 例如阻止等待来自客户端的连接的服务器。

答案 1 :(得分:2)

在模拟场景中,我想确保我在Task.WhenAny()块中的代码正在处理正在等待的任务之一,我可能会模拟其他任务并使用无限延迟来确保任务。当任何人正在处理任务时,我没有模仿无限延迟。

答案 2 :(得分:0)

当我希望控制台应用程序不终止时,我正在使用它。 例如,当我为Auzre编写 Web Job 时,我需要一个永不终止的程序。这是模板:

public async Task Main(string args[])
{
    var timer = new Timer();
    timer.Interval = 6000;
    timer.Elapsed += (sender, args) =>
    {
        // Do something repeatedly, each 1 minute.
    };
    timer.Start();

    // Now what to do to stop the application from terminating!?
    // That's the magic:
    await Task.Delay(-1);
}