首页 文章

SmtpClient.SendMailAsync方法是否安全线程?

提问于
浏览
5

SmtpClient Class表明实例成员不是线程安全的 . 如果对SendSendAsync进行并发调用,则可以看到这一点 . 如果第一个尚未完成,则两个方法都会在第二次调用时抛出InvalidOperationException .

.NET 4.5中引入的方法SendMailAsync未将InvalidOperationException列为抛出异常 . 新的.NET 4.5方法是否实现某种排队? Reflector无法阐明这个类的实现细节,因此我假设这已经在本机方法中实现 .

多个线程可以安全地调用SMTP客户端的共享实例上的SendMessageAsync方法吗?

2 回答

  • 10

    我不确定为什么使用Reflector不适合你 . 如果我反编译它,我看到以下代码:

    [HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)]
    public Task SendMailAsync(MailMessage message)
    {
        TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
        SendCompletedEventHandler handler = null;
        handler = delegate (object sender, AsyncCompletedEventArgs e) {
            this.HandleCompletion(tcs, e, handler);
        };
        this.SendCompleted += handler;
        try
        {
            this.SendAsync(message, tcs);
        }
        catch
        {
            this.SendCompleted -= handler;
            throw;
        }
        return tcs.Task;
    }
    

    如您所见,它是 SendAsync() 的简单TAP包装器 . 如果 SendAsync() 抛出异常, SendMailAsync() 只是重新抛出它 .

    因此,结论是 SendMailAsync() is not thread-safe 并且其例外情况未被记录 .

  • 2

    作为一个注释(因为我没有足够的评论点),编写异步操作的传统方法是使用异步编程模型(APM),但今天我们通常使用基于任务的异步模式(TAP)它的async / await关键字 . 虽然看到围绕APM方法的TAP包装并不罕见,但也可以看到围绕TAP方法的APM包装器 .

相关问题