首页 > 解决方案 > 异步发送邮件 C#

问题描述

前奏:我有一个异步发送邮件的 SendMail 方法和一个执行某些操作的 Add_Order 方法,如果传递的参数满足某些要求,则从中调用 SendMail 函数以向客户发送通知。

这就是问题所在:调用 SendMail 后,Add_Order() 会继续运行,试图删除一些被另一个进程阻止的文件。在 99% 的情况下,此过程是尚未完成其工作的 SendMail()。

如何修改此代码以解决此问题?如果有人可以帮助我,我真的很感激。谢谢你的建议

[HttpPost, Route("order_insert")]
    public HttpResponseMessage wsAdd_Order(wsOrdineTulero nOrdine)
    {
        ...

        sendMail(isProd ? rCustomer["MailingList"].ToString() : "f.mail@mail.it", "", ccn, (isProd ? "" : "[TEST] ") + "Tulero - Conferma di spedizione", string.Format(templateMail, mail), true, allegati);

        // This Foreach throw the error because these files are alredy taken by SendMail process 
        foreach (string s in allegati) { File.Delete(s); }
    }




private bool sendMail(string dest, string cc, string ccn, string oggetto, string testo, bool isHtml, string[] allegati)
    {
        try
        {
            SmtpClient smtpClient = new SmtpClient("", 25);

             ...   

            smtpClient.SendCompleted += (s, e) =>
            {
                string sQuery = helper.GetQuery("ADD_MAIL", new string[7] { mail.From.Address, dest, cc, ccn, oggetto, testo.Replace("'", "''"), allegati == null ? "" : string.Join("|", allegati) });
                try { helper.ExecuteSQLNonQuery(sQuery); }
                catch (Exception ex) { helper.NotifyLog(Severity.EXCEPTION_TRACE, ex, "Errore durante la registrazione della mail. Query:|" + sQuery); }
                smtpClient.Dispose();
                mail.Dispose();
            };
            smtpClient.SendAsync(mail, null);

            return true;
        }
        catch (Exception ex) { helper.NotifyLog(Severity.FATAL, ex, string.Format("Failed to send mail|dest: {0}|cc: {1}|ccn: {2}|oggetto: {3}|testo: {4}|isHtml: {5}|allegati: {6}", dest, cc, ccn, oggetto, testo, isHtml, allegati != null ? string.Join("|\\t", allegati) : "")); }
        return false;
    }

标签: c#email

解决方案


您需要使用异步等待模式。正如您自己所说,某些方法是异步执行的。

await您可以使用异步调用前面的关键字来阻止代码的执行。但是,为了让您使用await关键字,您需要标记调用它的方法async,因为它现在执行异步操作,这意味着它本身就是异步的。

这应该这样做:

[HttpPost, Route("order_insert")]
public async Task<HttpResponseMessage> wsAdd_Order(wsOrdineTulero nOrdine)
{
    var success = await sendMail(isProd ? rCustomer["MailingList"].ToString() : "f.mail@mail.it", "", ccn, (isProd ? "" : "[TEST] ") + "Tulero - Conferma di spedizione", string.Format(templateMail, mail), true, allegati);

    // This Foreach throw the error because these files are alredy taken by SendMail process 
    if (success) {
        foreach (string s in allegati) { File.Delete(s); }
    }
}

private async Task<bool> sendMail(string dest, string cc, string ccn, string oggetto, string testo, bool isHtml, string[] allegati)
{
    try
    {
        SmtpClient smtpClient = new SmtpClient("", 25);

        smtpClient.SendCompleted += (s, e) =>
        {
            string sQuery = helper.GetQuery("ADD_MAIL", new string[7] { mail.From.Address, dest, cc, ccn, oggetto, testo.Replace("'", "''"), allegati == null ? "" : string.Join("|", allegati) });
            try { helper.ExecuteSQLNonQuery(sQuery); }
            catch (Exception ex) { helper.NotifyLog(Severity.EXCEPTION_TRACE, ex, "Errore durante la registrazione della mail. Query:|" + sQuery); }
            smtpClient.Dispose();
            mail.Dispose();
        };
        await smtpClient.SendMailAsync(mail);

        return true;
    }
    catch (Exception ex) { helper.NotifyLog(Severity.FATAL, ex, string.Format("Failed to send mail|dest: {0}|cc: {1}|ccn: {2}|oggetto: {3}|testo: {4}|isHtml: {5}|allegati: {6}", dest, cc, ccn, oggetto, testo, isHtml, allegati != null ? string.Join("|\\t", allegati) : "")); }
    return false;
}

推荐阅读