How to set Async Page Directive Dynamically so Async Methods work

BigBlondeViking picture BigBlondeViking · Jul 2, 2009 · Viewed 7.3k times · Source

I am writing some Utility code to send off emails Async.

var mailClient = new SmtpClient(smtpHost);
mailClient.SendCompleted += new SendCompletedEventHandler(mailClient_SendCompleted);

using (var mailMessage = new MailMessage())
{
    if (!((System.Web.UI.Page)HttpContext.Current.CurrentHandler).IsAsync)
    {
        // set to Async????
    }
    mailClient.SendAsync(mailMessage, new { EmailID });
}

But I get errors because my Pages don't have Async="true" in the page directives.

here is the standard error that you get:

"Asynchronous operations are not allowed in this context. Page starting an
asynchronous operation has to have the Async attribute set to true and an
asynchronous operation can only be started on a page prior to
PreRenderComplete event."

I read this: (last paragraph )

http://msdn.microsoft.com/en-us/magazine/cc163725.aspx

A final point to keep in mind as you build asynchronous pages is that you should not launch asynchronous operations that borrow from the same thread pool that ASP.NET uses. For example, calling ThreadPool.QueueUserWorkItem at a page's asynchronous point is counterproductive because that method draws from the thread pool, resulting in a net gain of zero threads for processing requests. By contrast, calling asynchronous methods built into the Framework, methods such as HttpWebRequest.BeginGetResponse and SqlCommand.BeginExecuteReader, is generally considered to be safe because those methods tend to use completion ports to implement asynchronous behavior.

Questions:

1) How can I update the page to be Async in my c# code?

2) If I can't what is the down side with forcing all my pages to be Async=true?

3) Is there an even better way to thread my task without being "counterproductive"?

Answer

John Saunders picture John Saunders · Jul 2, 2009

How many different pages do you need to send mail from?

Also, what error did you get when you tried to send async? Please edit your question to contain the entire exception.

Consider creating a single (async) page to send email from. You can call that page by using Server.Transfer, and have it redirect back to your desired page when done.

Finally, if you're sending so many emails that you lose performance when sending mail synchronously, then perhaps you should create a Windows Service to send the actual email. Your ASP.NET page would queue a request to this service (through MSMQ, or WCF) to have the service send the email.