MST

星途 面试题库

面试题:C# 异步编程中的异常处理

在使用 Async 和 Await 进行异步编程时,异常处理与同步编程有哪些不同?请编写一段代码,演示在异步方法链中(即一个异步方法调用另一个异步方法,层层嵌套)如何正确捕获和处理异常。假设存在多个可能抛出不同类型异常的异步操作。
31.1万 热度难度
编程语言C#

知识考点

AI 面试

面试题答案

一键面试
  1. 异常处理与同步编程的不同
    • 在同步编程中,异常会立即中断当前代码的执行,并沿着调用栈向上抛出,直到被捕获。捕获异常使用try - catch块,在同步代码块内直接捕获异常。
    • 在使用AsyncAwait的异步编程中,异步方法返回TaskTask<T>,异常不会立即中断执行流。Await表达式会暂停当前异步方法的执行,直到所等待的Task完成。如果Task以故障状态完成(即抛出异常),Await会将该异常重新抛出,以便在当前异步方法中捕获处理。异常处理同样使用try - catch块,但要放在包含Await的异步方法内。
  2. 代码示例
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        try
        {
            await OuterAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"全局捕获到异常: {ex.Message}");
        }
    }

    static async Task OuterAsync()
    {
        try
        {
            await InnerAsync();
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"OuterAsync捕获到InvalidOperationException异常: {ex.Message}");
        }
    }

    static async Task InnerAsync()
    {
        await Task.Delay(1000);
        throw new InvalidOperationException("模拟InnerAsync抛出的InvalidOperationException异常");
    }
}

上述C#代码演示了在异步方法链中如何捕获和处理异常。InnerAsync方法模拟抛出一个InvalidOperationException异常,OuterAsync方法捕获该特定类型的异常进行处理,如果未被OuterAsync捕获,异常会继续向上抛出,在Main方法中被全局捕获。不同编程语言的AsyncAwait实现细节可能略有不同,但异常处理的核心思路一致。例如在Python中:

import asyncio


async def inner_async():
    await asyncio.sleep(1)
    raise ValueError("模拟inner_async抛出的ValueError异常")


async def outer_async():
    try:
        await inner_async()
    except ValueError as ex:
        print(f"outer_async捕获到ValueError异常: {ex}")


async def main():
    try:
        await outer_async()
    except Exception as ex:
        print(f"全局捕获到异常: {ex}")


if __name__ == "__main__":
    asyncio.run(main())

Python代码中同样展示了在异步方法链中捕获异常的过程,inner_async抛出ValueErrorouter_async捕获该异常,若未捕获则在main函数中全局捕获。