我只是想看看在等待冷任务(即尚未启动的 Task
)时会发生什么。令我惊讶的是,代码永远挂起,“Finsihed”从未打印出来。我希望抛出异常。
public async Task Test1()
{
var task = new Task(() => Thread.Sleep(1000));
//task.Start();
await task;
}
void Main()
{
Test1().Wait();
Console.WriteLine("Finished");
}
然后我想也许任务可以从另一个线程开始,所以我将代码更改为:
public async Task Test1()
{
var task = new Task(() => Thread.Sleep(1000));
//task.Start();
await task;
Console.WriteLine("Test1 Finished");
}
void Main()
{
var task1 = Test1();
Task.Run(() =>
{
Task.Delay(5000);
task1.Start();
});
task1.Wait();
Console.WriteLine("Finished");
}
但它仍然阻塞在task1.Wait()
。有谁知道等待后是否有办法开始冷任务?
否则似乎没有必要await
一个冷任务,所以也许任务应该在等待时启动或者应该抛出异常。
更新
我在等待错误的任务,即 Test1
返回的外部任务,而不是其中新增的任务。 @Jon Skeet 提到的 InvalidOperationException 被抛出到 Task.Run
中,但是由于没有观察到生成的任务,所以没有在主线程上抛出异常。将 try/catch
放入 Task.Run
或调用 Wait()
或 Result
返回的任务 Task.Run
在主控制台线程上抛出异常。
最佳答案
您正在尝试启动由异步方法返回的任务 - 那 不是您开始时使用的冷任务。事实上,如果您向 Task.Run
调用添加一些诊断,您会看到抛出异常:
System.InvalidOperationException: Start may not be called on a promise-style task.
这是一个展示我认为您真正想要做的事情的例子:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Test
{
static void Main(string[] args)
{
// Not using Task.Delay! That would be pointless
Task t1 = new Task(() => Thread.Sleep(1000));
Task t2 = Await(t1);
Console.WriteLine(t2.Status);
Console.WriteLine("Starting original task");
t1.Start();
Console.WriteLine(t2.Status);
t2.Wait();
Console.WriteLine(t2.Status);
}
static async Task Await(Task task)
{
Console.WriteLine("Beginning awaiting");
await task;
Console.WriteLine("Finished awaiting");
}
}
注意使用 Thread.Sleep
而不是 Task.Delay
;除非您使用 Task.Delay
的结果,否则它基本上什么都不做。使用 Thread.Sleep
模拟在其他任务中完成的实际工作。
至于为什么等待未启动的任务不会抛出异常 - 老实说,我认为这是合理的。它允许上述情况有效,这在某些情况下可能会使生活更轻松。 (例如,您可能会在开始之前创建很多任务 - 并且您可能希望在开始之前等待它们完成。)
关于c# - 为什么等待冷任务不抛出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24237266/