为什么等待寒冷任务不会抛出 [英] Why awaiting cold Task does not throw
问题描述
我只是尝试,看看当一个冷的任务(即一工作
其中尚未启动)是等待会发生什么。令我惊讶的code只是挂永远的Finsihed 的从不打印。我预计会抛出异常。
I was just experimenting to see what happens when a cold task (i.e. a Task
which hasn't been started) is awaited. To my surprise the code just hung forever and "Finsihed" is never printed. I would expect that an exception is thrown.
public async Task Test1()
{
var task = new Task(() => Thread.Sleep(1000));
//task.Start();
await task;
}
void Main()
{
Test1().Wait();
Console.WriteLine("Finished");
}
然后我虽然也许可以将任务从另一个线程开始,所以我改变了code为:
Then I though perhaps the task can be started from another thread, so I changed the code to:
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()
。有谁知道是否有方法来启动一个寒冷的任务,它已经被期待已久的后?
But it is still blocked at task1.Wait()
. Does anyone know if there is way to start a cold task after it has being awaited?
否则,它似乎还有在能够等待
寒冷的任务是没有意义的,所以也许任务应该要么等待时或异常应该抛出启动。
Otherwise it seems there is no point in being able to await
a cold task, so perhaps the task should either be started when awaited or an exception should be thrown.
更新
我在等待了错误的任务,即通过测试1
,而不是里面一个newed返回外任务。通过@乔恩飞碟双向提到的InvalidOperationException异常被抛出在 Task.Run
然而,由于没有观察到所产生的任务,异常被抛出不能在主线程。把一个的try / catch
在 Task.Run
或致电等待()
或结果
由 Task.Run
任务丢给主控台线程上的异常。
I was awaiting the wrong task, i.e. the outer task returned by Test1
rather than the one newed inside it. The InvalidOperationException mentioned by @Jon Skeet was being thrown inside Task.Run
however because the resulting task was not observed, the exception was not thrown on the main thread. Putting a try/catch
inside Task.Run
or calling Wait()
or Result
on the task returned by Task.Run
threw the exception on the main console thread.
推荐答案
您正试图通过启动异步方法返回的任务 - 的是的不是你开始御寒任务。事实上,如果你添加一些诊断你的 Task.Run
电话,你会看到一个异常被抛出:
You're trying to start the task returned by the async method - that isn't the cold task that you started out with. Indeed, if you add some diagnostics to your Task.Run
call, you'll see that an exception is thrown:
System.InvalidOperationException:开始可能不会被要求承诺式的任务
System.InvalidOperationException: Start may not be called on a promise-style task.
下面是显示什么,我觉得你真的想做一个例子:
Here's an example showing what I think you were really trying to do:
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代码
是模拟实际工作中的其他任务来完成。
Note the use of Thread.Sleep
instead of Task.Delay
; unless you're using the result of Task.Delay
, it basically does nothing. Using Thread.Sleep
is emulating real work to be done in the other task.
至于为什么等待一个尚未启动的任务不会抛出异常 - 我认为这是合理的,是诚实的。它允许像上述情况是有效的,这可能在某些情况下,使生活更轻松。 (你可以启动它们,例如之前创造了很多的任务 - 你可能要开始等着你开始之前他们完成)
As for why awaiting an unstarted task doesn't throw an exception - I think that's reasonable, to be honest. It allows for situations like the above to be valid, which may in some cases make life easier. (You may create a lot of tasks before starting them, for example - and you may want to start waiting for them to finish before you start them.)
这篇关于为什么等待寒冷任务不会抛出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!