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

时间:2013-04-08 20:23:59

标签: c# .net-4.5 async-await

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

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

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

2 个答案:

答案 0 :(得分: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()不是线程安全的,并且其例外情况未被记录。

答案 1 :(得分:2)

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