【问题标题】:Does Task.Wait(int) start waiting right when it's called, or when the Task starts running?Task.Wait(int) 是否在被调用时开始等待,或者在任务开始运行时开始等待?
【发布时间】:2019-02-27 03:11:58
【问题描述】:

这是一个非常微妙的问题,但我的好奇心占了上风,我无法在文档或 SO 的其他地方找到答案。

Task.Wait(int millisecondsTimeout) 的文档说:

等待任务在指定的毫秒数内完成执行。

返回:

true 如果任务在分配的时间内完成执行;否则,false

考虑一下这个sn-p:

Task task = Task.Run(() => {
    Thread.Sleep(2000);
});
task.Wait(1000);

当我调用Task.Wait(...) 时,超时倒计时是立即开始,还是Wait(...) 首先等待任务真正开始运行,然后才开始倒计时? (Task.Run(...) 仅使 Task 有资格运行。并不保证它确实已启动)

例如,如果线程池中的所有线程都在使用,并且线程池必须延迟 0.5 秒才能为我的队列任务创建新线程,我的 Wait(1000) 调用是否会在整秒,还是 0.5 秒后?

如果我猜的话,我会说Wait(...) 将在整整一秒后返回,但我想确定一下。

【问题讨论】:

  • 看起来这对你来说很容易测试。
  • @JohnWu 我创建了一个小测试,但结果很奇怪且不确定。不过,这并不像答案中的测试那么简单......
  • @pushkin 简单。等待你从未开始的任务。它要么达到超时并继续,要么永远不会超时,具体取决于它是哪个选项。
  • @Servy 你的意思是使用Task 构造函数并且从不调用Start?我对您调用Start(或Run)的情况很感兴趣,但是由于线程池中的所有其他线程都忙,因此任务排队并延迟运行。
  • @Servy 虽然你的例子与我打算测试的有点不同,但它的结果确实回答了我的问题(见下面的答案)。谢谢

标签: c# multithreading task task-parallel-library wait


【解决方案1】:

由于通过我的阅读,您可以很容易地测试场景以自己找出答案,我不确定我是否真的理解您的要求。也就是说,会这样测试它:

static void Main(string[] args)
{
    Task task = new Task(() => WriteLine("task!"));

    task.Wait(1000);

    WriteLine("Done waiting");
}

果然,如果你运行上面的代码,你会发现即使你从未启动过任务,对Wait()的调用仍然会在1秒后过期。

换句话说,正如文档所说,该方法等待任务完成指定的时间,然后返回。

鉴于Wait() 方法即使任务从未启动也会返回,如果任务已启动但还没有机会运行任何代码,它也会返回。听起来这实际上就是您要询问的场景。

任务是否启动是无关紧要的(尽管在实践中,这些天我们几乎从来没有未启动的任务......良好的惯用 C# 编程实践规定您只能从返回已启动任务的机制中获取 Task 对象,例如Task.Run() 或调用async 方法)。

或者这样看:如果你妈妈告诉你,“我会在你打扫完房间后立即提供晚餐,但不迟于现在 30 分钟”,你认为她会接受吗?考虑您是否真的开始打扫房间?不,无论如何,她都会在 30 分钟后上桌。

.NET 也是如此。它不关心你是否开始了任务,只是它没有在分配的时间内完成。

【讨论】:

  • 即使使用Task.Run,在调用它之后你“知道”的只是Task 正在运行或将在未来运行(所有其他条件都相同) )。其他一些代码块可能刚刚用大量未声明的长时间运行的操作淹没了线程池......
  • @Damien_The_Unbeliever:是的,我想这取决于你对“开始”的定义。对我来说,这不是从池中将线程分配给任务的问题,甚至不是计划在 CPU 内核上执行的线程的问题,而是任务是否有资格执行的问题。在你“开始”一个任务之前,它甚至没有资格执行;一旦你“开始”一项任务,它可能会或可能不会马上做任何工作,但它(在我看来)肯定开始
  • 我的世界观倾向于TaskStatus。 :-)
  • @Damien_The_Unbeliever:但是,我同意你的观点。我认为您是说 OP 可能不是对任务是否已开始(根据我的定义)感到好奇,而是对它是否有机会运行感到好奇。话虽如此,我认为如果 Wait() 方法将返回,即使任务从未启动过,它也会在任务已启动但没有机会运行任何代码的情况下返回,这是公平的然而。 :)
  • @PeterDuniho 是的,我对任务何时有资格执行不感兴趣,但它何时实际运行。你的例子提供了一个很好的推论,我没有考虑尝试。 “如果即使任务从未启动,Wait() 方法也会返回,如果任务已经启动,它也会返回,但还没有机会运行任何代码。”回答我的问题 - 谢谢
猜你喜欢
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 1970-01-01
相关资源
最近更新 更多