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

邮件发送成功但C#程序执行await SendEmailAsync后停滞,如何解决?

问题分析与解决方案

你的程序在执行await client.SendEmailAsync(mail)后停滞不前,核心原因是同步等待异步方法引发的死锁,再加上代码里的一些潜在问题,导致后续流程完全无法执行。下面是具体的分析和修复步骤:

核心死锁原因

你在Main方法里用.Wait()同步等待AutoSendMessage这个异步方法,而await关键字会捕获当前的线程上下文。当SendEmailAsync完成后,await试图回到原来的上下文继续执行,但原来的线程已经被.Wait()阻塞,导致两个环节互相等待,程序直接卡死在这一步,自然不会执行后续代码。

另外,当前的异常处理逻辑在死锁场景下根本不会触发,因为方法根本没机会走到catch块,这也让你无法看到真正的问题所在。

具体修复步骤

1. 将Main方法改为异步(C# 7.1及以上支持)

控制台程序从C# 7.1开始支持异步Main方法,这是解决同步等待死锁的最优方案,彻底避免阻塞问题:

static async Task Main(string[] args) {
    // 保留你原来的初始化、循环逻辑...
    // 最后一行替换为异步等待,去掉.Wait()
    await program.AutoSendMessage(emailcontent);
}

如果你的项目还没开启C# 7.1+,可以在项目属性的「Build」→「Advanced」里设置「Language version」为7.1或更高版本。

2. 完善异常处理,避免吞掉关键错误

当前的AutoSendMessage只打印异常消息,会丢失堆栈跟踪、内部异常等关键调试信息,修改后让错误更清晰:

private static async Task AutoSendMessage(string Message) {
    try {
        var client = new SendGridClient("API_KEY");
        var from = new EmailAddress("xxxxxx", "xxxxxxx");
        var subject = "Extra Information from API_Item Master(Item, ItemCode, Item Category) Program ";
        var messagedetail = Message;
        var to = new EmailAddress("xxxxxxxx", "xxxx");
        var plainTextContent = "Hello, Email from the helper !" + messagedetail;
        var htmlContent = "<strong>Please check the Following Information:- </strong>" + messagedetail;
        var mail = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
        
        var response = await client.SendEmailAsync(mail);
        
        // 新增:检查邮件发送响应,确认是否真的成功
        if (!response.IsSuccessStatusCode) {
            var responseBody = await response.Body.ReadAsStringAsync();
            throw new InvalidOperationException($"邮件发送失败,状态码:{response.StatusCode},响应内容:{responseBody}");
        }
    } catch(Exception ex) {
        Console.WriteLine($"发送邮件出错:{ex.Message}");
        Console.WriteLine($"错误堆栈:{ex.StackTrace}");
        if (ex.InnerException != null) {
            Console.WriteLine($"内部异常:{ex.InnerException.Message}");
        }
        // 如果需要上层处理这个异常,可以重新抛出
        throw;
    }
}

3. 修复数据库资源泄漏问题

你的代码里SqlCommand、SqlDataReader没有用using语句包裹,会导致数据库连接无法及时释放,引发资源泄漏。修改示例:

private DataTable GetExtraItemTypeFromTarget(string SourceDB, string targetDB) {
    DataTable dt = new DataTable();
    string sql = "select t.ItemType ItemType from " + targetDB + ".dbo.ItemType t where " +
                 "not exists(select * from " + SourceDB + ".dbo.ItemType s where t.ItemType = s.ItemType) ";
    
    // 使用using自动释放SqlCommand资源
    using(SqlCommand ExtraItemTypeCommand = new SqlCommand(sql, dbConnection)){
        ExtraItemTypeCommand.CommandTimeout = 180;
        // 使用using自动释放SqlDataReader资源
        using(SqlDataReader ExtraItmeTypeReader = ExtraItemTypeCommand.ExecuteReader()){
            dt.Load(ExtraItmeTypeReader);
        }
    }
    return dt;
}

4. 规避SQL注入风险

当前SQL语句直接拼接targetDB参数,存在严重的SQL注入风险。建议对targetDB做白名单验证,确保传入的数据库名是合法的已知值,避免恶意输入破坏数据库。

修复后效果

修改完成后,程序会:

  • 异步等待邮件发送完成,彻底解决死锁问题,后续流程正常执行
  • 若邮件发送失败,会打印完整的错误信息,方便快速定位问题
  • 数据库资源会被自动释放,避免连接泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:27:49