Don’t make your users wait unnecessarily. For example, a page where you generate a PDF and send it to someone else. Hand the job off to an asynchronous process and move on.
There are a lot of ways this can be done, but the easiest seems to be using a Thread. However, you run into a problem with having parameters. A parameterizedThread can actually only have ONE parameter…. but it can be an object, so that means you can jam all sorts of cool things in there.
Here is a example of a parameterized thread
First, you make a nice class to hold your parameters:
Class mailParams Public mTo As String Public mFrom As String Public subject As String Public body As String Public attachmentMemoryStream As MemoryStream Public attachmentFileName As String Public archiveFile As String End Class
Then we have a subroutine attached to a button that does a fire-and-forget email. Basically, it just says, “send that..” and continues to process the page. You get refreshed practically instantly.
protected sub btnSendMail_OnClick(sender as object, e as eventargs) handles btnSendMail.click Dim objMailParams As New mailParams objMailParams.mTo = strTo objMailParams.mFrom = strFrom objMailParams.subject = strSubject objMailParams.body = strMessage Dim asyncMailObj As New System.Threading.ParameterizedThreadStart(AddressOf sendAnEmail) Dim t As New System.Threading.Thread(asyncMailObj) t.Start(objMailParams) end sub
That ParameterizedThreadStart simply assigns a CPU thread to kick off the subroutine “sendAnEmail”. I preloaded the class of parameters and used the entire class as a single object parameter.
sub sendAnEmail(obj as object) Dim mp As mailParams = obj '=== I keep all my settings for mail and connection strings in a class called DataLayer. Dim myServer As New DataLayer.mailSettings Dim objMM As New MailMessage Dim objSMTP As New SmtpClient Dim m As New MailMessage() Dim mTo As New System.Net.Mail.MailAddress(mp.mTo) Dim mFrom As New System.Net.Mail.MailAddress(mp.mFrom) objMM.To.Add(mTo) objMM.From = mFrom objMM.IsBodyHtml = False objMM.Priority = MailPriority.Normal objMM.Subject = mp.subject objMM.Body = mp.body objSMTP.Host = myServer.smtpServer objSMTP.DeliveryMethod = SmtpDeliveryMethod.Network objSMTP.Credentials = New System.Net.NetworkCredential(myServer.smtpUser, myServer.smtpPassword) objSMTP.EnableSsl = False objSMTP.Send(objMM) end sub
Now, this is a very simple example. The reason I started doing this is because I was generating PDF invoices by screen captures, then sending an archive of the PDF up to Amazon’s S3 storage, then emailing the pdf to the client. Some of the invoices were 20 pages long. The server can handle the workload, but people couldn’t handle the wait. So, fire-and-forget.
Later on, if it becomes a problem, I’ll see about putting in some kind of confirmation emails that say whether or not the invoice actually got sent.
If it becomes a server memory issue, I’ll update this post with whatever solution I came up with next!