Почему программа Send-Email зависает?
Я сделал небольшую программу, в которой я могу отправлять электронную почту через SMTP-сервер Yahoo. Мой код:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Net;
using System.Net.Mail;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
MailMessage message = new MailMessage();
message.From = new MailAddress("myid@yahoo.com");
message.To.Add("anotherid@yahoo.com");
message.Subject = "afdasdfasfg";
message.Body = "Hgfk4564267862738I";
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com");
sC.Port = 587;
sC.Credentials = new NetworkCredential("myid", "mypassword");
//sC.EnableSsl = true;
sC.Send(message);
MessageBox .Show ("Mail Send Successfully");
}
catch (Exception ex)
{
MessageBox .Show (ex + "Mail Sending Fail's") ;
}
}
}
}
Странно то, что он работал в течение первой недели. Я мог бы отправлять сообщения без проблем. Тогда как раз вчера программа просто зависает и не отвечает (я не менял код). Почему это случилось? Как я могу исправить свою программу?
Редактировать: @Andreas Niedermair Прямо сейчас я только что попробовал программу и оставил ее на целую минуту, после чего появилась ошибка: обнаружен ContextSwitchDeadlock Сообщение: CLR не удалось перейти из контекста COM 0x21eb78 в контекст COM 0x21ece8 в течение 60 секунд. Поток, который владеет целевым контекстом / квартирой, скорее всего либо выполняет некачивающее ожидание, либо обрабатывает очень длительную операцию без прокачки сообщений Windows. Эта ситуация, как правило, оказывает негативное влияние на производительность и может даже привести к тому, что приложение перестает отвечать на запросы или постоянно накапливается использование памяти. Чтобы избежать этой проблемы, все потоки однопоточных квартир (STA) должны использовать примитивы перекачки (такие как CoWaitForMultipleHandles) и регулярно перекачивать сообщения во время длительных операций.
Спасибо за вашу помощь!
2 ответа
Ваш catch
когда-нибудь достигать?
я предполагаю, что вы недостаточно терпеливы, чтобы достичь значения по умолчанию Timeout
свойство (100 секунд)... вы можете уменьшить значение, чтобы получить более раннее завершение.
до тех пор, пока вы не работаете с асинхронным шаблоном, ваш поток пользовательского интерфейса в любом случае блокируется. альтернативой будет использовать SendAsync
метод (в msdn-записях есть конкретные реализации для конкретных методов).
Редактировать:
как автор упомянул возможный порт **, да, это может быть. но вам придется прочитать документ с техническими условиями, который говорит нам:
- SMTP-сервер: plus.smtp.mail.yahoo.com
- Использовать SSL
- Порт: 465
- Использовать аутентификацию
- Имя учетной записи / Имя для входа: Ваш Yahoo! Идентификатор почты (ваш адрес электронной почты без "@yahoo.com", например, "testing80")
- Адрес электронной почты: Ваш Yahoo! Почтовый адрес (например, testing80@yahoo.com)
- Пароль: Ваш Yahoo! Почтовый пароль
- [...] попробуйте установить номер порта SMTP на 587 при отправке электронной почты через SMTP-сервер Yahoo!.
но даже если вы соответствуете спецификациям: вы действительно должны использовать асинхронный шаблон:)
Изменить: упомянутое исключение связано с COM ... немного гуглинг, и я нашел это:
Вероятно, происходит то, что у вас есть COM-объект в форме, и вы работаете с потоком пользовательского интерфейса. Если ваш пользовательский интерфейс блокируется обработкой в течение>60 секунд, компонент COM может пожаловаться.
Редактировать:
иначе: вы что-нибудь изменили в диалоге исключений Visual Studio? тогда это может быть вашим решением или этим (с некоторыми базовыми объяснениями)...
Согласно правке Андреаса Нидермейра, проблема заключается в том, что вы блокируете основной поток более чем на 60 секунд. Лучше всего сделать эту операцию в фоновом потоке.
using System;
using System.ComponentModel;
using System.Net;
using System.Net.Mail;
using System.Windows.Forms;
namespace Sandbox_Form
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
bw = new BackgroundWorker();
bw.DoWork +=new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Error != null)
MessageBox.Show(e.Error.ToString() + "Mail Sending Fail's") ;
else
MessageBox.Show("Mail Send Successfully");
}
BackgroundWorker bw;
void bw_DoWork(object sender, DoWorkEventArgs e)
{
using(MailMessage message = new MailMessage())
{
message.From = new MailAddress("myid@yahoo.com");
message.To.Add("anotherid@yahoo.com");
message.Subject = "afdasdfasfg";
message.Body = "Hgfk4564267862738I";
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
using(SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com"))
{
sC.Port = 587;
sC.Credentials = new NetworkCredential("myid", "mypassword");
//sC.EnableSsl = true;
sC.Send(message);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
bw.RunWorkerAsync();
}
}
}
РЕДАКТИРОВАТЬ:
Согласно предложению Андреаса Нидермейра, здесь есть версия с использованием асинхронного метода.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
MailMessage message = new MailMessage();
message.From = new MailAddress("myid@yahoo.com");
message.To.Add("anotherid@yahoo.com");
message.Subject = "afdasdfasfg";
message.Body = "Hgfk4564267862738I";
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
SmtpClient sC = new SmtpClient("smtp.mail.yahoo.com");
sC.Port = 587;
sC.Credentials = new NetworkCredential("myid", "mypassword");
//sC.EnableSsl = true;
//sC.Send(message);
sC.SendCompleted += new SendCompletedEventHandler(sC_SendCompleted);
sC.SendAsync(message, null);
}
catch (Exception ex)
{
MessageBox.Show(ex + "Mail Sending Fail's");
}
}
void sC_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
if(e.Error != null)
MessageBox.Show(ex + "Mail Sending Fail's");
else
MessageBox.Show("Mail Send Successfully");
}
}