Send Email without waiting for the action to finish execution after Button click ASP.NET

In short, remaining in the HTTP context, I would like the user, after clicking on an order completion button, not to wait for the mails to be sent before being sent back to a “thak you page”.

I saw that HostingEnvironment.QueueBackgroundWorkItem could help me with this but there is always the risk of it being killed by IIS recycling.

What is the best solution to do this?

I know the best would be to develop a separate console solution but it wouldn’t be worth it for 3/4 emails, alternatively I could consider speeding it up by making them asynchronous?

Protected Sub btnConcludiOrdine_Click(sender As Object, e As System.EventArgs) Handles btnConcludiOrdine.Click
    If IsValidOrder(Me._cart, msg) Then
      If Me._cart.SaveOrder(Me._user, Me._orderCode, Me._lang) then
           'Update quantity in db
           Dim mail As New EmailBLL
           mail.SendOrderNotice(Me._cart, Me._lang) '2 Mails
           mail.SendProductNotice() '2 Mails
      End If
    Else
      Response.Redirect("*Error URL*")
    End If
End Sub

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

The way you approach this is as suggested – start a task, or so called new processor thread.

So, what you would do is break out the code – this even works if code behind is for a web form.

So, the first step is to move out the “slow” parts, or the parts we want to run separate.

The main issue is that to start/launch/want/desire/achieve a brand new processor thread?

The sub call CAN ONLY PASS ONE “parameter” and the sub can only accept one parameter!!!!!

I note in your case that routine needs two values.

However, that “one parameter” can be a array of “many” values, or even a collection or whatever. In our case we pass the two values.

So just keep in mind that what you call can NOT update or “use” the values of controls on the form – the instance of that form will go out of scope.

But we can of course PASS the values you need. This will allow that routine to run 100% independent of the web form.

I also VERY strong suggest that if you DO place the sub in the same web page code behind? You should/can mark that sub as shared. Doing so will allow the compiler to get mad at you and spit out errors if that routine say tries to use or update a control value on the form.

However, it is MUCH better is to place this sub in a separate standard code module out side of the web forms code behind.

Regardless of above, we can now re-write the code we have as this:

If Me._cart.SaveOrder(Me._user, Me._orderCode, Me._lang) then
       
       Dim myInfo(1) as object
       myInfo(0) = me.cart
       myInfo(1) = me_._lng

       Call MyUpdateQ(myInfo) 
  End If
  ' bla bla lba


Shared Sub MyUPdateQ(p() as object)

       'Update quantity in db
       Dim mail As New EmailBLL

       mail.SendOrderNotice(p(0),p(1) 
       mail.SendProductNotice() '2 Mails

End Sub

Ok, so far, we not achieved much, but we re-writing to accept the ONE array is KEY here.

So, now now make sure the above runs/works and is all happy.

Now, because we moved out the “work load” to that one routine, it is now a simple matter to start a thread.

Now, Our above code becomes this:

Protected Sub btnConcludiOrdine_Click(sender As Object, e As System.EventArgs) Handles btnConcludiOrdine.Click

   If IsValidOrder(Me._cart, msg) Then
      If Me._cart.SaveOrder(Me._user, Me._orderCode, Me._lang) then
         Dim myInfo(1) as object
         myInfo(0) = me.cart
         myInfo(1) = me_._lng

         Dim MyThread As New Thread(New ParameterizedThreadStart(AddressOf MyUpdateQ))

         MyThread.Start(myInfo)
      End If
   Else
      Response.Redirect("*Error URL*")
   End If
End Sub

Shared Sub MyUPdateQ(p() as object)

       'Update quantity in db
       Dim mail As New EmailBLL

       mail.SendOrderNotice(p(0),p(1) 
       mail.SendProductNotice() '2 Mails

End Sub

That is it. Now when you click your button it will wait ZERO time, since the long running routine is now going to run 100% as a separate thread. And this will also mean that when the user clicks the button – the page will respond instant and post back to user will be done. So if that thread takes 6 seconds, or even 25 seconds, the user will not notice this delay.

Method 2

Just push your sending mail logic in Task and if you are not interested in result don’t await it. c# syntax

Task.Run(() => SendEmail());


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x