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

SmtpClient.SendAsync标记为异步却返回void,是否为真异步?

关于SmtpClient中标记为async却返回void的方法的异步实现问题

Great question! Let’s break this down to understand exactly what’s happening here.

First, the short answer: yes, this method is truly asynchronous—it’s not a synchronous operation masquerading as async. The confusion stems from it using an older .NET asynchronous pattern instead of the modern Task-based approach you might expect.

Why async with a void return?

This method follows the Event-based Asynchronous Pattern (EAP), which was widely used in .NET before the Task-based Asynchronous Pattern (TAP) and async/await became the standard. EAP methods are designed to return void and use events to notify callers when the async operation finishes—here, that’s the SendCompleted event on SmtpClient.

The async keyword is present because the internal implementation uses await to handle asynchronous I/O flow cleanly, but since it’s adhering to the EAP contract, it returns void instead of a Task. It’s worth noting that async void methods are generally discouraged outside of event handlers (since they have tricky exception handling behavior), but this is a legacy design choice to maintain compatibility with older codebases.

How does it handle async without Task?

Under the hood, the method relies on traditional .NET asynchronous mechanisms:

  • It uses the Asynchronous Programming Model (APM) pattern, which uses paired methods like BeginSend/EndSend for network socket operations (since SMTP is a network protocol). These methods kick off async I/O without blocking the calling thread.
  • It may also queue work to the ThreadPool to offload non-I/O-bound async work, ensuring the main thread stays responsive.
  • When the operation completes (successfully, with an error, or if cancelled), it triggers the SendCompleted event, passing details via AsyncCompletedEventArgs—including any errors, cancellation status, or a user-provided token you passed in.

How to use this method correctly

To work with this async method properly, you need to subscribe to the SendCompleted event before invoking it:

var smtpClient = new SmtpClient("your-smtp-server-address");
var mailMessage = new MailMessage(
    "sender@example.com", 
    "recipient@example.com", 
    "Hello!", 
    "This is an async test email."
);

// Subscribe to the completion event first
smtpClient.SendCompleted += (sender, args) => {
    if (args.Error != null)
    {
        Console.WriteLine($"Email failed to send: {args.Error.Message}");
    }
    else if (args.Cancelled)
    {
        Console.WriteLine("Send operation was cancelled.");
    }
    else
    {
        Console.WriteLine("Email sent successfully!");
    }

    // Clean up resources once done
    smtpClient.Dispose();
    mailMessage.Dispose();
};

// Start the asynchronous send operation
smtpClient.SendAsync(mailMessage, null);

A quick modern note

If you’re working with .NET Core 3.0 or later, keep in mind that SmtpClient is marked obsolete. The recommended alternative is using libraries like MailKit, which fully support modern TAP with Task-returning async methods, making async code easier to write and maintain.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:40:09