简体   繁体   中英

Sending email within .NET Task not working in console application

I have the following code below. This runs at the end of my console application. I am not receiving emails that go out when it is done within the task, but when I comment out the task factory method it works? The code gets his both times with a breakpoint but the async email flow doesn't ever send out the email. Any reason why?

Task.Factory.StartNew(() =>
{ 
    var smtp = new SmtpClient();
    try
    {
        var toEmails = mailMessage.To.ToList();
        var bccEmails = mailMessage.Bcc.ToList();

        foreach (var email in toEmails)
        {
           mailMessage.To.Clear();
           mailMessage.To.Add(email);
           mailMessage.Bcc.Clear();

           smtp.Send(mailMessage);
        }
     }
     catch (Exception ex)
     {
       Logger.Error(ex);
     }
});

As you say "This runs at the end of my console application" , i am assuming your Main method is terminating before Task.Factory.Startnew has a chance to finish running your code in the background thread.

You should either:

  1. Run this code synchronously, without starting a new thread (this would be my recommended approach)
  2. Explicitly wait for the task to finish using Task.Wait while blocking the execution of your Main method, which misses the point of using a ThreadPool thread at all (i wouldn't do this):

     Task.Factory.StartNew(() => { var smtp = new SmtpClient(); try { var toEmails = mailMessage.To.ToList(); var bccEmails = mailMessage.Bcc.ToList(); foreach (var email in toEmails) { mailMessage.To.Clear(); mailMessage.To.Add(email); mailMessage.Bcc.Clear(); smtp.Send(mailMessage); } } catch (Exception ex) { Logger.Error(ex); } }).Wait(); 

Edit

I had to add that i would advice you NOT to consume the code from the common library, for a few reasons:

  1. It previously returned void and was spinning a redundant ThreadPool thread to do IO based work
  2. This will cause you to have to use Wait on a new thread, you dont need that.

If you want to consume a true async api (one which doesn't need to use a thread to execute IO bound work) you can use SmtpClient.SendMailAsync and simply await on it:

var smtp = new SmtpClient();
try
{
    var toEmails = mailMessage.To.ToList();
    var bccEmails = mailMessage.Bcc.ToList();

    var taskMails = toEmails.Select(email => 
    {
        var message = new MailMessage
        {
            To = email
        };

        smtp.SendMailAsync(message);
    };

    await Task.WhenAll(taskEmails);
 }
 catch (Exception ex)
 {
   Logger.Error(ex);
 }

I made the return type of Task which gave me the option to wait or not.

 var task = _emailService.Send(new List<string> { @event.ContactEmail }, subject, body,
                    new List<Attachment>
                        {
                            new Attachment(new MemoryStream(bytes), report.FileName, "application/pdf")
                        });

                if (task != null)
                {
                    task.Wait();
                }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM