【发布时间】:2014-01-02 16:22:39
【问题描述】:
在一个 WinForms 应用程序中,我运行多个 BackgroundWorker 来发送批量电子邮件。 (不,这不是垃圾邮件,而是公司电子邮件)。
发送电子邮件时,有时会发生SmtpException('发送邮件失败')。此 SmtpException 在 try-catch 中抛出并写入日志。但是,当这个异常特别发生时,将异常写入日志并继续大约需要 5 分钟,之后每封电子邮件都会失败并出现相同的异常(处理每封失败的电子邮件大约需要 5 分钟)。
根据我的研究,我了解到当在调试模式下引发未处理的异常时,BackgroundWorker 会停止。但是,我已经使用调试和发布配置运行了该项目,并且行为是相同的。 即使在调试模式下,BackgroundWorker 也会停止很长时间,而调试器不会弹出任何异常消息。
另请注意,此错误很难重现,因为第一个带有消息“发送邮件失败”的 SmtpException 在看似随机的点发送了 300-800 封电子邮件时引发。
对于日志记录,我只是使用 System.Diagnostics 中的 Trace,所以我认为这不是问题。
编辑:我还应该补充一点,在极少数情况下,当 SmtpException 出现消息“发送邮件失败”时,BackgroundWorker 会完全停止处理电子邮件。我让它挂在那里只是为了它的地狱,大约 1 小时后它继续发送电子邮件,就像什么都没发生一样。
DoWork 的代码如下:
private void sender_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
SalaryEmail[] emails = e.Argument as SalaryEmail[];
SmtpClient smtpClient = new SmtpClient("smtp.office365.com", 587);
smtpClient.EnableSsl = true;
smtpClient.Credentials = new NetworkCredential(SalaryEmail.SmtpCredentials.User, SalaryEmail.SmtpCredentials.Password);
foreach (SalaryEmail email in emails)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Sending and database operations here
email.Send(ref smtpClient);
// In this case I only report progress to a progressBar with previously set steps, so the number is irrelevant
worker.ReportProgress(0);
}
}
smtpClient.Dispose();
}
这是 SalaryEmail.Send:
public bool Send(ref SmtpClient smtpClient)
{
bool sent = false;
for (int i = 0; i < MAX_ATTEMPTS; i++)
{
try
{
// Mail is a System.Net.Mail.MailMessage non-static property created and configured previously within the class
smtpClient.Send(Mail);
sent = true;
}
catch (SmtpException smtpEx)
{
Trace.WriteLine(DateTime.Now + " Intento " + i + " SmtpException: " + smtpEx.Message);
}
catch (Exception ex)
{
Trace.WriteLine(DateTime.Now + " Intento " + i + " Error al enviar: " + ex.Message);
}
// Update database
if (sent)
{
try
{
Database.MarkAsSent(Qna, RFC);
}
catch (Exception e)
{
Trace.WriteLine(DateTime.Now + " Error al marcar enviados" + e.Message);
}
break;
}
}
return sent;
}
异常详情:
A first chance exception of type 'System.Net.Mail.SmtpException' occurred in System.dll
02/01/2014 12:57:25 Intento 0 SmtpException: System.Net.Mail.SmtpException: Error al enviar correo. ---> System.Net.WebException: Se excedió el tiempo de espera de la operación.
en System.Net.ConnectionPool.Get(Object owningObject, Int32 result, Boolean& continueLoop, WaitHandle[]& waitHandles)
en System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralAsyncDelegate asyncCallback, Int32 creationTimeout)
en System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
en System.Net.Mail.SmtpTransport.GetConnection(ServicePoint servicePoint)
en System.Net.Mail.SmtpClient.GetConnection()
en System.Net.Mail.SmtpClient.Send(MailMessage message)
--- Fin del seguimiento de la pila de la excepción interna ---
en System.Net.Mail.SmtpClient.Send(MailMessage message)
en MailingClient.SalaryEmail.Send(SmtpClient& smtpClient) en C:\Users\mrivera\Documents\Visual Studio 2010\Projects\PayrollMailing\MailingClient\SalaryEmail.cs:línea 62
追踪:
02/01/2014 1:44:56 Sending email...
02/01/2014 1:45:01 Updating database...
02/01/2014 1:45:01 Sending email...
02/01/2014 1:45:06 Updating database...
02/01/2014 1:45:07 Sending email...
02/01/2014 1:45:11 Updating database...
02/01/2014 1:45:11 Sending email...
<exception posted above here>
The thread '<No Name>' (0x1890) has exited with code 0 (0x0).
The thread '<No Name>' (0x444) has exited with code 0 (0x0).
The thread '<No Name>' (0xb90) has exited with code 0 (0x0).
The thread '<No Name>' (0x1b00) has exited with code 0 (0x0).
The thread '<No Name>' (0x2754) has exited with code 0 (0x0).
The thread '<No Name>' (0x978) has exited with code 0 (0x0).
The thread '<No Name>' (0x1a68) has exited with code 0 (0x0).
The thread '<No Name>' (0x18b0) has exited with code 0 (0x0).
The thread '<No Name>' (0x1b68) has exited with code 0 (0x0).
The thread '<No Name>' (0x24fc) has exited with code 0 (0x0).
The thread '<No Name>' (0x18c0) has exited with code 0 (0x0).
The thread '<No Name>' (0xa1c) has exited with code 0 (0x0).
【问题讨论】:
-
看一下 InnerException 看看它是否给你一个更好的线索。我的猜测是服务器无法跟上大量传入请求,5 分钟对我来说听起来像是超时。
-
@WonkotheSane Smtp 超时异常也会发生,但它们得到了正确处理。消息“提交率已超出”也有一个例外,该消息也得到了正确处理。我将再次重现它并查看 InnerException,并将结果发回此处。
-
@WonkotheSane 我的 Visual Studio 是西班牙语,所以我会尽力翻译内部异常消息:“无法将数据写入传输连接。现有连接已被远程主机中断”
-
'提交率已超过',然后服务器应用 5 分钟超时限制。谜团解开了。
-
贴出的代码无关紧要,显示(主要部分)email.Send()
标签: c# email smtp backgroundworker