c# - 为什么等待冷任务不抛出

标签 c# asynchronous async-await

我只是想看看在等待冷任务(即尚未启动的 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/

相关文章:

c# - ICollection<>.Contains 在 EF 中,因为 HashSet 失败

c# - 玻璃 : Solution found, 上的渲染控件需要双缓冲/完善

c# - Windows 7 上的 LINQ 性能较慢

c# - asp.net-mvc-2中的分页

javascript - 如何重新排序异步函数的执行顺序?

c# - 在 Windows 8 中写入文件时异步

c# - 异步并等待 : multiple await expressions

javascript - 等待后未执行异步/等待代码

c# - 使用泛型作为异步方法的返回类型

javascript - 等待相当于 'Promise.resolve().then()' ?