[英]Why can SmtpClient.SendAsync only be called once?
我正在嘗試使用SmtpClient在.NET中編寫通知服務(用於完全合法的非垃圾郵件目的)。 最初我只是通過每個消息循環並發送它,但這很慢,我想提高速度。 所以,我切換到使用'SendAsync',但現在第二次調用時出現以下錯誤:
An asynchronous call is already in progress.
我讀到這意味着MS癱瘓System.Net.Mail以防止群發郵件。 這個對嗎? 如果是這樣,有沒有更好的方法在.NET中執行此操作,並且仍然能夠記錄每封電子郵件的結果(這對我們的客戶來說很重要)。 如果沒有,為什么SendAsync只能被調用一次?
您可以使用以下內容:
ThreadPool.QueueUserWorkItem(state => client.Send(msg));
這應該允許您的消息排隊並在線程可用時發送。
顯然,這不是企圖阻止群發郵件。
原因是SmtpClient類不是線程安全的。 如果要同時發送多個電子郵件,則必須生成一些工作線程(在.NET Framework中有幾種方法可以執行此操作)並在每個線程中創建單獨的SmtpClient實例。
我認為你誤解了XXXAsync
類的方法。 這些異步調用的目的是允許程序繼續運行,而不需要方法來完成處理並首先返回。 然后,您可以通過訂閱對象的XXXReceived
事件來繼續處理結果。
要同時發送多個郵件,您可以考慮使用更多的Thread
。
您每個SMTP客戶端一次只能發送一個。 如果您希望進行多個發送呼叫,請創建多個SMTP客戶端。
HTH,
科爾比非洲
正如這里的其他人所注意到的,你一次只能發送一封電子郵件,但是發送第一封電子郵件后發送另一封電子郵件的方法是處理SmtpClient類的.SendCompleted事件,然后轉到下一封電子郵件,發送。
如果您想同時發送許多電子郵件,那么就像其他人所說的那樣,使用多個SmtpClient對象。
有理由重用SmtpClient ,它限制了與SMTP服務器的連接數。 我無法為報告構建的每個線程實例化一個新的類SmtpClient類,或者SMTP服務器將忽略太多的連接錯誤。 這是我在這里找不到答案時提出的解決方案。
我最終使用AutoResetEvent來保持所有內容同步。 這樣,我可以繼續在每個線程中調用SendAsync ,但是等待它處理電子郵件並使用SendComplete事件重置它,以便下一個可以繼續。
我設置了自動重置事件。
AutoResetEvent _autoResetEvent = new AutoResetEvent(true);
我的類實例化時設置了共享SMTP客戶端。
_smtpServer = new SmtpClient(_mailServer);
_smtpServer.Port = Convert.ToInt32(_mailPort);
_smtpServer.UseDefaultCredentials = false;
_smtpServer.Credentials = new System.Net.NetworkCredential(_mailUser, _mailPassword);
_smtpServer.EnableSsl = true;
_smtpServer.SendCompleted += SmtpServer_SendCompleted;
然后當我調用send async時,我等待事件清除,然后發送下一個事件。
_autoResetEvent.WaitOne();
_smtpServer.SendAsync(mail, mail);
mailWaiting++;
我使用SMTPClient SendComplete事件重置AutoResetEvent,以便下一封電子郵件發送。
private static void SmtpServer_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MailMessage thisMesage = (MailMessage) e.UserState;
if (e.Error != null)
{
if (e.Error.InnerException != null)
{
writeMessage("ERROR: Sending Mail: " + thisMesage.Subject + " Msg: "
+ e.Error.Message + e.Error.InnerException.Message);
}
else
{
writeMessage("ERROR: Sending Mail: " + thisMesage.Subject + " Msg: " + e.Error.Message);
}
}
else
{
writeMessage("Success:" + thisMesage.Subject + " sent.");
}
if (_messagesPerConnection > 20)
{ /*Limit # of messages per connection,
After send then reset the SmtpClient before next thread release*/
_smtpServer = new SmtpClient(_mailServer);
_smtpServer.SendCompleted += SmtpServer_SendCompleted;
_smtpServer.Port = Convert.ToInt32(_mailPort);
_smtpServer.UseDefaultCredentials = false;
_smtpServer.Credentials = new NetworkCredential(_mailUser, _mailPassword);
_smtpServer.EnableSsl = true;
_messagesPerConnection = 0;
}
_autoResetEvent.Set();//Here is the event reset
mailWaiting--;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.