2013-04-08 7 views
5

SmtpClient Classは、インスタンスメンバーがスレッドセーフではないことを示しています。これは、同時呼び出しがSendまたはSendAsyncに行われた場合に発生します。両方のメソッドは、最初のコールがまだ完了していない場合、2番目のコールでInvalidOperationExceptionをスローします。SmtpClient.SendMailAsyncメソッドはスレッドセーフですか?

.NET 4.5に導入されたSendMailAsyncメソッドは、Throw例外としてInvalidOperationExceptionをリストしません。新しい.NET 4.5メソッドは何らかの種類のキューイングを実装しますか? Reflectorはこのクラスの実装の詳細については何も明らかにすることができないので、これはネイティブメソッドで実装されていると仮定します。

複数のスレッドがSMTPクライアントの共有インスタンス上でSendMessageAsyncメソッドを安全に呼び出すことはできますか?

+1

スレッドセーフではないメソッドは、複数のスレッドからアクセスすると例外をスローする必要はありません。 – svick

答えて

10

反射板を使用した理由がわかりません。私はそれを逆コンパイルした場合、私は次のコードを参照してください。

[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()はスレッドセーフではありませんとその例外は文書化されていません。

+0

私は自分のキューイングの仕組みを実装していないと思います。応答していただきありがとうございます。 – brianfeucht

+0

@brianfeucht代わりに 'SmtpClient'の複数のインスタンスを使用するのはなぜですか(各スレッドに1つ)? – svick

+0

それは計画です。 SmtpClientのプールを作成して、マシンの接続数を制御できるようにします。クライアントが利用可能な場合、共有されます。プールが完全に使用されている場合、要求は次に使用可能なクライアントのためにキューに入れられます。 – brianfeucht

2

非同期操作を記述する伝統的な方法は、非同期プログラミングモデル(APM)を使用することでしたが、今日では通常、タスクベースの非同期パターンを使用しています(TAP)に非同期/待機キーワードを設定します。また、APMメソッドの周りにTAPラッパーを表示するのは珍しいことではありませんが、TAPメソッドの周りにAPMラッパーを表示することも可能です。

関連する問題