首页 > 解决方案 > 为什么等待之前的异常不会在没有等待的情况下抛出?

问题描述

考虑以下代码:

static async Task ThrowException()
{
    throw new Exception("exception 1");
    Thread.Sleep(1000);
    await Task.Delay(1000);
    throw new Exception("exception 2");
}
static async Task Sleep()
{
    Console.WriteLine("begin sleep");
    Thread.Sleep(1000);
    Console.WriteLine("end sleep");
    Console.WriteLine("begin delay");
    await Task.Delay(1000);
    Console.WriteLine("end delay");
}
static async Task Main(string[] args)
{
    {
        Console.WriteLine("begin var task = Sleep();");
        var task = Sleep();
        Console.WriteLine("end var task = Sleep();");
        Console.WriteLine("begin await task;");
        await task;
        Console.WriteLine("end await task;");
    }
    {
        try
        {
            Console.WriteLine("begin var task = ThrowException();");
            var task = ThrowException();
            Console.WriteLine("end var task = ThrowException();");
            Console.WriteLine("begin await task;");
            await task;
            Console.WriteLine("end await task;");
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

结果如下:

begin var task = Sleep();
begin sleep
end sleep
begin delay
end var task = Sleep();
begin await task;
end delay
end await task;
begin var task = ThrowException();
end var task = ThrowException();
begin await task;
exception 1

我的问题是为什么exception 1出现在“开始等待任务”任务之后但“结束睡眠”出现在“开始等待任务”之前?我认为它之前没有启动一个新线程await Task.Delay(),它应该发生在同一个线程中Thread.Sleep(),所以我希望在“end var task = ThrowException();”之前立即抛出“异常 1”

标签: c#

解决方案


这段代码是

static async Task ThrowException()
{
    throw new Exception("exception 1");
    Thread.Sleep(1000);
    await Task.Delay(1000);
    throw new Exception("exception 2");
}

如同

static Task ThrowException()
{
    Task.Run(() =>
        {
            throw new Exception("exception 1");
            Thread.Sleep(1000);
            await Task.Delay(1000);
            throw new Exception("exception 2");
        }
    )
}

诀窍是异常被任务吞噬。然后异常存储在任务中,当您询问任务的结果时,抛出异常。并await返回任务的结果。

在你的情况下:

try
{
    Console.WriteLine("begin var task = ThrowException();");
    // 1) Display : "begin var task = ThrowException();"
    var task = ThrowException();
    // 2) Starts a task that immediately ends with an exception
    Console.WriteLine("end var task = ThrowException();");
    // 3) Display : "end var task = ThrowException();"
    Console.WriteLine("begin await task;");
    // 4) Display : "begin await task;"
    await task;
    // 5) await return the task result,
    // in this case it's throw the exception stored in the task.
    // Go to in catch
    Console.WriteLine("end await task;");
    var task = ThrowException();
    await task;
}
catch(Exception e)
{
    Console.WriteLine(e.Message);
    //6) Display the exception message
}

推荐阅读