特にSendAsyncを使用して呼び出しを行う場合、SmtpClientを使い捨てできるようになったため、SmtpClientの管理方法について少し困惑しています。おそらく、SendAsyncが完了するまでDisposeを呼び出さないでください。しかし、これを呼び出す必要があります(たとえば、「使用」を使用)。このシナリオは、呼び出しが行われたときに定期的に電子メールを送信するWCFサービスです。ほとんどの計算は高速ですが、電子メールの送信には数秒かかる場合があるため、非同期が望ましいでしょう。
メールを送信するたびに新しいSmtpClientを作成する必要がありますか? WCF全体に1つ作成する必要がありますか?助けて!
更新違いが生じる場合、各メールは常にユーザーに合わせてカスタマイズされます。 WCFはAzureでホストされ、Gmailはメーラーとして使用されます。
注:.NET 4.5 SmtpClientはasync awaitable
メソッドSendMailAsync
を実装しています。下位バージョンの場合は、以下で説明するようにSendAsync
を使用します。
IDisposable
インスタンスは、できるだけ早く廃棄する必要があります。非同期呼び出しの場合、これはメッセージが送信された後のコールバックにあります。
var message = new MailMessage("from", "to", "subject", "body"))
var client = new SmtpClient("Host");
client.SendCompleted += (s, e) => {
client.Dispose();
message.Dispose();
};
client.SendAsync(message, null);
SendAsync
がコールバックを受け入れないのは少し面倒です。
元の質問は.NET 4に対して尋ねられましたが、それが.NET 4.5の時点で役立つ場合、SmtpClientは非同期待機可能メソッド SendMailAsync
を実装します。
その結果、非同期で電子メールを送信することは次のとおりです。
public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage)
{
using (var message = new MailMessage())
{
message.To.Add(toEmailAddress);
message.Subject = emailSubject;
message.Body = emailMessage;
using (var smtpClient = new SmtpClient())
{
await smtpClient.SendMailAsync(message);
}
}
}
SendAsyncメソッドの使用は避けたほうがよいでしょう。
一般に、IDisposableオブジェクトはできるだけ早く破棄する必要があります。オブジェクトにIDisposableを実装することは、問題のクラスが決定的に解放されるべき高価なリソースを保持しているという事実を伝えることを目的としています。ただし、これらのリソースの作成に費用がかかり、これらのオブジェクトを大量に作成する必要がある場合は、1つのインスタンスをメモリに保持して再利用する方が(パフォーマンス面で)優れている場合があります。それが違いを生むかどうかを知る唯一の方法があります。それをプロファイリングしてください!
Re:破棄と非同期:using
は明らかに使用できません。代わりに、通常、SendCompletedイベントでオブジェクトを破棄します。
var smtpClient = new SmtpClient();
smtpClient.SendCompleted += (s, e) => smtpClient.Dispose();
smtpClient.SendAsync(...);
SmtpClientを破棄することが特に重要である理由は、次のコメントで確認できます。
public class SmtpClient : IDisposable
// Summary:
// Sends a QUIT message to the SMTP server, gracefully ends the TCP connection,
// and releases all resources used by the current instance of the System.Net.Mail.SmtpClient
// class.
public void Dispose();
クライアントを破棄せずにGmailを使用して複数のメールを送信する私のシナリオでは、次のものを入手していました。
メッセージ:サービスを利用できません。伝送チャネルを閉じています。サーバーの応答:4.7.0一時的なシステムの問題。後でもう一度試してください(WS)。 oo3sm17830090pdb.64-gsmtp
わかった、古い質問。しかし、似たようなものを実装する必要があるときに、私は自分でこれを見つけました。コードを共有したかっただけです。
複数のメールを非同期に送信するために、複数のSmtpClientを繰り返し処理しています。私のソリューションはTheCodeKingに似ていますが、代わりにコールバックオブジェクトを破棄しています。また、MailMessageをuserTokenとして渡して、SendCompletedイベントで取得し、disposeを呼び出すこともできます。このような:
foreach (Customer customer in Customers)
{
SmtpClient smtpClient = new SmtpClient(); //SmtpClient configuration out of this scope
MailMessage message = new MailMessage(); //MailMessage configuration out of this scope
smtpClient.SendCompleted += (s, e) =>
{
SmtpClient callbackClient = s as SmtpClient;
MailMessage callbackMailMessage = e.UserState as MailMessage;
callbackClient.Dispose();
callbackMailMessage.Dispose();
};
smtpClient.SendAsync(message, message);
}