2

I have a winforms application from which the user can send an email. This email is sent async and not awaited (fire and forget)

The method calling the email async instantiates a class (EmailSender) which does all of the work of composing the email, sending it and logging the result in the database. I expect that wrapping EmailSender in a using statement will create problems with resources still working async trying to complete. However, if I just instantiate the class and call EmailSender.Send(), the resources will not be properly disposed.

What is the best way to proceed here while still managing the resources properly. Am I better of throwing all of this into static methods which manage their own resources or do I completely misunderstand the issue here

//Fire and forget
EmailSender es = new EmailSender(itemId);
es.Send();



public class EmailSender
{

    public EmailSender(int ItemId)
    {
        //initialise stuff
    }

    public async void SendAsync()
    {
        string emailContent = getEmailContent();
        using (MailMessage mail = new MailMessage())
        {
            using (SmtpClient client = emailManager.getSMTPSettings())
            {
                try
                {
                    string fromSender = emailManager.getEmailFrom();
                    if (!string.IsNullOrEmpty(fromSender)) mail.From = new MailAddress(fromSender);
                    //etc
                    await client.SendMailAsync(mail);
                }
                catch
                { //log to db}
                }
            }
        }
    }

    private string getEmailContent()
    {
        return "content";
    }
}

EDIT: I want the async code to continue in the background after the form is closed and users move through to different parts of the application.

statler
  • 1,322
  • 2
  • 15
  • 24
  • 1
    What is the reason for not awaiting `SendAsync`? – FCin Mar 08 '18 at 12:00
  • If the instance of the class you instatiated is still alive, your resources will not be discarded automatically. Use the dispose interface to manually free your resource. – King of the North Mar 08 '18 at 12:09
  • I have edited to clarify - I want the code to continue after the form is closed. Basically users fill in information, and then submit the form. This fires the emails independently in the background. – statler Mar 08 '18 at 12:13
  • What framework are you using? `Asp.net`? `Wpf`? – FCin Mar 08 '18 at 12:21
  • What if you could make your EmailSender an IDisposable as you wish and call es.SendAsync().ContinueWith(task => es.Dispose())? Just make sure to not use as using(var sender = new EmailSender(...)), just do the regular var sender = new EmailSender(...) and dispose this object after the task completes – Mari Faleiros Mar 08 '18 at 12:41
  • Thanks Mari, my concern is that the task is called from the form class, if the form is closed and the form class disposed, then what happens to the task? Is it disposed too? Will the async task complete? – statler Mar 08 '18 at 20:13
  • FCin. Just a regular winforms app – statler Mar 08 '18 at 20:13

1 Answers1

-1

if the async Method returns Task, you can call it like SendAsync().Wait();

Marius Steinbach
  • 548
  • 7
  • 19