brianfeucht
brianfeucht

Reputation: 794

Are the SmtpClient.SendMailAsync methods Thread Safe?

The SmtpClient Class states that instance members are not thread safe. This can be seen if concurrent calls are made to Send or SendAsync. Both methods will throw a InvalidOperationException on the second call if the first has not yet completed.

The method SendMailAsync, introduced in .NET 4.5, does not list InvalidOperationException as a thrown exception. Do the new .NET 4.5 methods implement some sort of queuing? Reflector isn't able to shed any light on the implementation details of this class, so I assume this has been implemented in native methods.

Can multiple threads call the SendMessageAsync method on a shared instance of the SMTP client safely?

Upvotes: 9

Views: 7507

Answers (2)

Moe Howard
Moe Howard

Reputation: 157

As a note (since I don't have enough points to comment), the traditional way to write an asynchronous operation was to use the Asynchronous Programming Model (APM), but today we typically use the Task-based Asynchronous Pattern (TAP) with its async/await keywords. And although it's not unusual to see TAP wrappers around APM methods, it's also possible to see APM wrappers around TAP methods.

Upvotes: 2

svick
svick

Reputation: 244777

I'm not sure why using Reflector didn't work for you. If I decompile it, I see the following code:

[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;
}

As you can see, it's a simple TAP wrapper for SendAsync(). And if SendAsync() throws an exception, SendMailAsync() just rethrows it.

So, the conclusion is that SendMailAsync() is not thread-safe and that its exceptions are underdocumented.

Upvotes: 14

Related Questions