C#smtp异步发送未发送

C#smtp异步发送未发送,c#,smtp,sendasync,C#,Smtp,Sendasync,我正在尝试通过sendasync发送电子邮件。问题是它似乎没有进入sendcompleted事件处理程序。我在那里添加了一个断点,但它从未触发。程序只是在我的信号灯处等待。有什么想法吗?该程序是一个windows窗体应用程序 if (send) { print("Starting to send mail to " + Globalcls.projects[i].name); mailSendSe

我正在尝试通过sendasync发送电子邮件。问题是它似乎没有进入sendcompleted事件处理程序。我在那里添加了一个断点,但它从未触发。程序只是在我的信号灯处等待。有什么想法吗?该程序是一个windows窗体应用程序

if (send)
          {
                    print("Starting to send mail to " + Globalcls.projects[i].name);
                    mailSendSemaphore = new Semaphore(0, 1);
                    System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
                    msg.To.Add(Globalcls.projects[i].email);
                    msg.From = new MailAddress(Globalcls.settings.server_email);
                    msg.Subject = "Data";
                    msg.SubjectEncoding = System.Text.Encoding.UTF8;
                    msg.Body = "Please see attached data";
                    msg.BodyEncoding = System.Text.Encoding.UTF8;
                    msg.IsBodyHtml = false;
                    msg.Priority = MailPriority.High;

                    foreach (string fileName in files)
                    {
                       msg.Attachments.Add(new System.Net.Mail.Attachment(fileName));
                    }


                    SmtpClient client = new SmtpClient();
                    client.Credentials = new System.Net.NetworkCredential(Globalcls.settings.username, Globalcls.settings.password);
                    client.Port = Convert.ToInt32(Globalcls.settings.portS);//or use 587 

                    client.Host = "smtp.xdsl.co.za";

                    client.SendCompleted += new SendCompletedEventHandler(MailSendCallback);

                    client.SendAsync(msg,null);
                    mailSendSemaphore.WaitOne();
                   // if (Globalcls.error_message != "")
                      //  throw Exception
                    //client.Dispose();
                    print("email sent to " + Globalcls.projects[i].name);
                    client.Dispose();
                    mailSendSemaphore.Dispose();
                    msg.Dispose();

                }

                //Array.ForEach(Directory.GetFiles(GlobalClass.projects[i].foldero), delegate(string path) { File.Delete(path); });
                System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(Globalcls.projects[i].foldero);
                foreach (System.IO.FileInfo file in directory.GetFiles()) file.Delete();
                foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);


            }
这是我的OnSendHandler

        private static void MailSendCallback(object sender, AsyncCompletedEventArgs arg)
    {
        // oncomllete event for async send.
        if (arg.Error != null)
        Globalcls.error_message = arg.Error.ToString();

        // Release the main thread
        mailSendSemaphore.Release();
    }
编辑

我想使用sendasync的原因是sendasync显然在等待文件上传完成。当前的问题是,有时附件太大,以至于上传所需时间超过超时时间。我可以延长超时时间,但我不知道应该延长多长时间。大多数电子邮件很容易达到3mb。我们的adsl线路并不总是最稳定的

等待异步发送的原因是每个客户端不能有多个发送。这就是为什么我要等它结束

我的问题更多地与超时有关。我想要一个超时,只有当smtp和smtp客户端之间没有通信时才会超时

编辑2

这就是我的代码最初的样子。我想尽量避免那个巨大的超时。多线程只会使gui不挂起

if (send)
                {
                    print("Starting to send mail to " + Globalcls.projects[i].name);
                  //  mailSendSemaphore = new Semaphore(0, 1);
                    System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
                    msg.To.Add(Globalcls.projects[i].email);
                    msg.From = new MailAddress(Globalcls.settings.server_email);
                    msg.Subject = "Data";
                    msg.SubjectEncoding = System.Text.Encoding.UTF8;
                    msg.Body = "Please see attached data";
                    msg.BodyEncoding = System.Text.Encoding.UTF8;
                    msg.IsBodyHtml = false;
                    msg.Priority = MailPriority.High;

                    foreach (string fileName in files)
                    {
                       msg.Attachments.Add(new System.Net.Mail.Attachment(fileName));
                    }


                    SmtpClient client = new SmtpClient();
                    client.Credentials = new System.Net.NetworkCredential(Globalcls.settings.username, Globalcls.settings.password);
                    client.Port = Convert.ToInt32(Globalcls.settings.portS);//or use 587 

                   // client.Host = "127.0.0.1";
                    client.Host = "smtp.xdsl.co.za";
                    client.Timeout = 400000;
                    client.Send(msg);

                   /* client.SendCompleted += new SendCompletedEventHandler(MailSendCallback);

                    client.SendAsync(msg,null);
                    mailSendSemaphore.WaitOne();*/
                   // if (Globalcls.error_message != "")
                      //  throw Exception

                    print("email sent to " + Globalcls.projects[i].name);
                    client.Dispose();
                   //mailSendSemaphore.Dispose();
                    msg.Dispose();

                }

                //Array.ForEach(Directory.GetFiles(GlobalClass.projects[i].foldero), delegate(string path) { File.Delete(path); });
                System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(Globalcls.projects[i].foldero);
                foreach (System.IO.FileInfo file in directory.GetFiles()) file.Delete();
                foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);


            }
            catch (Exception ex)
            {
                print("Error with " + Globalcls.projects[i].name);
                print(ex.ToString());
                timer1.Enabled = false;
                timer1.Stop();
                btn_start.Enabled = true;
                string contents = "There was an error in sending mail to " + Globalcls.projects[i].name;
                string heading = " Anxo error";
                string subject = "Anxo error";
                errormail(heading, subject, contents, ex.ToString(), Globalcls.projects[i].sos);
                result = false;
            }

安装IIS/SmtpService并让它处理上载。i、 e.使用
SmtpClient
将电子邮件发送到
localhost:25
=本地IIS

我想这样做可以得到更为固体的溶液。因为IIS将继续尝试在出现故障时上载消息

更新

大概是这样的:

public class EmailSender
{
    ConcurrentQueue<MailMessage> _queue = new ConcurrentQueue<MailMessage>();
    private Thread _worker;
    ManualResetEvent _trigger = new ManualResetEvent(false);
    private bool _shutdown;

    public EmailSender()
    {
        _worker = new Thread(SendEmails);
        _worker.Start();
    }
    public void Enqueue(MailMessage message)
    {
        _queue.Enqueue(message);
        _trigger.Set();
    }

    public void Shutdown()
    {
        _shutdown = true;
        _trigger.Set();
        _worker.Join();
    }

    private void SendEmails(object state)
    {
        while (true)
        {
            _trigger.WaitOne(Timeout.Infinite);
            if (_shutdown)
                return; // you might want to send all emails instead.

            MailMessage msg;
            if (!_queue.TryDequeue(out msg))
            {
                _trigger.Reset();
                continue;
            }

            SendEmail(msg);
        }
    }

    private void SendEmail(MailMessage msg)
    {
        var client = new SmtpClient(); // configure
        try
        {
            client.Send(msg);
        }
        catch(SmtpException)
        {
            // try again. You might not want to retry forever = fix
            _queue.Enqueue(msg);
        }

    }
}
公共类EmailSender
{
ConcurrentQueue_queue=新的ConcurrentQueue();
私人线程(worker),;
ManualResetEvent _触发器=新的ManualResetEvent(错误);
私人楼宇关闭;
公共电子邮件发送者()
{
_工作者=新线程(发送电子邮件);
_worker.Start();
}
公共无效排队(邮件消息)
{
_排队(消息);
_trigger.Set();
}
公共空间关闭()
{
_关机=真;
_trigger.Set();
_worker.Join();
}
私有无效发送电子邮件(对象状态)
{
while(true)
{
_trigger.WaitOne(Timeout.Infinite);
如果(_关闭)
return;//您可能希望改为发送所有电子邮件。
邮件消息;
if(!\u queue.TryDequeue(out msg))
{
_trigger.Reset();
继续;
}
发送电子邮件(msg);
}
}
私人void sendmail(MailMessage msg)
{
var client=new SmtpClient();//配置
尝试
{
client.Send(msg);
}
捕获(SmtpException)
{
//重试。您可能不想永远重试=修复
_queue.Enqueue(msg);
}
}
}

为什么要在等待完成时异步发送?这种模式没有任何好处。只需使用
Send
SendAsync
用于希望调用线程停止并执行其他操作,而不是等待Send操作完成的情况。由于在sempahore的帮助下阻塞,所以不能发送async。您为什么要尝试完成?请参阅编辑。评论太大,无法在这里插入。我们公司的一些白痴认为最好删除我们的本地电子邮件托管,完全依靠远程托管。所以我并不认为这是一个可行的解决方案。这不是托管,只是电子邮件转发。如果不可行,您应该创建一个发送者队列,而不是像您那样阻塞。由于您应该考虑故障(如网络故障),请注意:我还检查了MSDN中的
SmtpClient.Send()
。它也应该等待完成。这是我一直得到的例外。“System.Net.Mail.SmtpException:操作已超时。”我甚至尝试将超时设置为240000,从100000到400000次,但我正在探索smtp服务routeYeah。你需要有一个巨大的超时。您的邮件提供商应该能够处理多个连接(即创建多个
SmtpClient
,每个电子邮件发送一个),我发现我可以发送电子邮件。但我似乎无法用outlook删除电子邮件。这只适用于不包含附件的电子邮件。只要它们包含附件,它就会失败。