You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用async/await的控制台应用异步数据库连接故障排查

问题排查与解决方案

核心问题分析

你遇到的崩溃问题根源是**async void方法的异常处理机制缺陷**:

  • async void类型的方法中抛出的异常无法被调用方的try/catch捕获,会直接绕过常规异常处理流程,触发进程级别的未处理异常,导致程序无提示崩溃。
  • 当你移除async/await时,FullUpdateAsync会被当作"即发即弃"的任务执行,主线程不会等待异步操作完成,所以会提前输出菜单内容。

具体修复步骤

1. 修改Run方法的返回类型

将IConsoleApp和ConsoleApp中的Run方法从async void改为async Task:

public interface IConsoleApp
{
    Task Run(string[] args);
}

public class ConsoleApp : IConsoleApp
{
    private readonly IMyService _myService;
    private readonly IMapper _mapper;

    public ConsoleApp(IMyService myService, IMapper mapper)
    {
        _myService = myService;
        _mapper = mapper;
    }

    public async Task Run(string[] args)
    {                     
        try
        {
            // code removed for brevity.
            
            while (true)
            {                
                Console.WriteLine("Please choose an option:");                    
                Console.WriteLine("1. Full update");
                
                Console.Write("Enter your choice: ");

                var choice = Console.ReadLine();

                switch (choice)
                {                        
                    case "1":
                        await _myService.FullUpdateAsync(objectIds);
                        break;                        
                    default:
                        Console.WriteLine("Invalid choice. Please try again.");
                        break;
                }                     
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("An error occurred: " + ex.Message);
        }        
    }
}

2. 异步化Main方法

控制台应用的Main方法支持异步返回类型,修改为async Task Main并等待Run方法执行:

public class Program
{
    public static async Task Main(string[] args)
    {
        using var host = CreateHostBuilder(args).Build();

        using var scope = host.Services.CreateScope();
        var consoleApp = scope.ServiceProvider.GetRequiredService<IConsoleApp>();
        await consoleApp.Run(args);
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {                    
                services.AddScoped<IMyService, MyService>();
                services.AddScoped<IConsoleApp, ConsoleApp>();
            });
}

3. 优化异常处理(可选)

如果希望FullUpdateAsync的异常仅在方法内处理,可移除内部的throw语句(根据业务需求调整):

public async Task FullUpdateAsync(List<int> objectIds)
{            
    try
    {
        foreach (var objectId in objectIds)
        {
            using (var connSource = new SqlConnection(_connstringSource))             
            {
                await connSource.OpenAsync();
                // code removed for brevity
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Exception: {ex.Message}");
        // 若不需要将异常抛回上层,可移除以下语句
        // throw;
    }
}

关键原理说明

  • 异步方法返回Task/Task<T>时,异常会被封装到返回的Task中,调用方通过await可以正常捕获这些异常。
  • async void仅适用于UI事件处理等特殊场景,控制台应用中绝对避免使用,否则会导致异常无法被捕获进而崩溃。
  • 当你移除async/await直接调用FullUpdateAsync时,方法返回的Task不会被等待,主线程会继续执行后续代码,因此菜单会提前显示。

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:31:03