0

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);


            }

これが私の onsendcomplete 偶数ハンドラーです

        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 を使用する理由は、send async が明らかにファイルのアップロードが完了するのを待っているからです。現在の問題は、添付ファイルが大きすぎて、アップロードにタイムアウトよりも時間がかかる場合があることです。タイムアウトを長くすることはできますが、どのくらい長くするべきかわかりません。ほとんどのメールは簡単に 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;
            }
4

1 に答える 1

0

IIS / SmtpServiceをインストールし、アップロードを処理できるようにします。つまり、 =ローカルIISSmtpClientに電子メールを送信するために使用します。localhost:25

そうすることで、より確実な解決策が得られます。何かが失敗した場合、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);
        }

    }
}
于 2012-09-11T06:03:30.563 に答える