ASP.NET MVC & Threads

I have a method that handles sending of emails.  I wrote it so that it would run asynchronously, so that it won’t slow down the web app.  It looks like this:

protected static void SendMail(string to, string subject, string body)
{
    try
    {
        using (var bgw = new BackgroundWorker())
        {
            bgw.DoWork += new DoWorkEventHandler(delegate
                                                     {
                                                         try
                                                         {
                                                             Thread.Sleep(15000);
                                                             using (MailMessage message = new MailMessage())
                                                             {
                                                                 message.From = new MailAddress(AdminEmail,
                                                                                                AdminName);
                                                                 message.To.Add(new MailAddress(to));
                                                                 message.Subject = subject;
                                                                 message.Body = body;
                                                                 message.IsBodyHtml = false;

                                                                 SmtpClient mailClient = new SmtpClient();
                                                                 mailClient.Send(message);
                                                             }
                                                         }
                                                         catch (Exception ex)
                                                         {
                                                             Utils.Log(ex);
                                                         }
                                                     });

            bgw.RunWorkerAsync();
        }
    }
    catch (Exception ex)
    {
        Utils.Log(ex);
    }
}

I added the Thread.Sleep(15000) to see if it works.  To my surprise, it didn’t.  For some reason, the web request doesn’t return until the email thread is done executing.  When I step through the code, it runs through the code right away without waiting and calls the return method on the controller as expected.  But the response is actually never sent to the server until the thread completes – which defies the whole point of it being asynchronous.

What am I doing wrong?  Is this a bug in the MVC framework?  Or did I just overlook something?

[UPDATE]

I am not sure what’s wrong with the code above but I re-wrote it as show below and it works very well.

protected static void SendMail(string to, string subject, string body)
{
   try
   {
       var t1 = new Thread(SendMailAsync);
       t1.Start(new string[] {to, subject, body});
   }
   catch (Exception ex)
   {
       Utils.Log(ex);
   }
}

private static void SendMailAsync(object emailInfo)
{
   try
   {
       
       var paramArray = emailInfo as string[];
       if (paramArray != null)
       {
           var to = paramArray[0];
           var subject = paramArray[1];
           var body = paramArray[2];

           using (MailMessage message = new MailMessage())
           {
               message.From = new MailAddress(AdminEmail,
                                              AdminName);
               message.To.Add(new MailAddress(to));
               message.Subject = subject;
               message.Body = body;
               message.IsBodyHtml = false;

               var mailClient = new SmtpClient();
               mailClient.Send(message);
           }
       }
   }
   catch (Exception ex)
   {
       Utils.Log(ex);
   }
}
Advertisements

0 thoughts on “ASP.NET MVC & Threads

  1. Emad, BackgroundWorker is designed just for Windows apps AFAIK. Also with your updated code you run the risk of running out of threads if you just create them on the fly like that. I would suggest you use ThreadPool.QueueUserWorkItem()

    Like

  2. Emad, BackgroundWorker is designed just for Windows apps AFAIK. Also with your updated code you run the risk of running out of threads if you just create them on the fly like that. I would suggest you use ThreadPool.QueueUserWorkItem()

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s