0

I have an application in which an action triggers a number of emails to be sent out. The number of emails is variable and can be anywhere from 10 to 1,000 per action.

I don't want the application to hang while the emails are being sent (thus annoying the user) and would like to send them in the background.

I haven't used Threads in the past so that's why I need your help. Would you create Threads manually or is this a good case to use a ThreadPool? I want this task to be low priority and use the least amount of resources possible because I don't mind even if the email is 1 hour late.

Appreciate your help
Marko

Marko
  • 71,361
  • 28
  • 124
  • 158

5 Answers5

3

Truthfully, threading in ASP.NET is not a good idea. Asp.net does a lot of disposing of resources when a request ends and posts back to the user. Since you don't want the user to wait, you'll run into this scenario, where ASP.NET objects you think are safe to use, are really disposed.

Your best option is to create an external service (either a wcf service running in IIS, or a windows service which has a wcf interface exposed) which the .net page can call asynchronously, and have that request run until it completes. No worrying about threading etc. It runs in it's own process and when it's done it completes. Since you don't care about telling the user that's done, you won't have to worry about it communicating back. This way to, if you need to have some other page use the same service interface, it's there to be called.

Pages on getting started with WCF:

http://bloggingabout.net/blogs/dennis/archive/2007/04/20/wcf-simple-example.aspx

http://msdn.microsoft.com/en-us/library/bb332338.aspx

http://www.c-sharpcorner.com/Articles/ArticleListing.aspx?SectionID=1&SubSectionID=192

How to start using WCF/WPF?

Community
  • 1
  • 1
kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • Thanks @Kevin that definitely sounds promising. What are your thoughts on the TaskParallel library of c# 4.0? I haven't worked with WCF services so it'll likely take some time for me to implement your solution. – Marko Nov 09 '10 at 21:17
  • The task parallel library is pretty neat, but personally, if you don't care about how long it will take to complete, I would avoid it. There is no point in introducing external complexity in a project where you don't need it. If you are looking to remove the threading problem I talked about, the task library won't get around it. I'll find some examples on starting WCF for you too. – kemiller2002 Nov 09 '10 at 21:23
  • Your solution seems like the best one, but my lack of experience with WCF means that I'd have to spend a lot of time developing it and would probably get it wrong the first few times. The solution seems like the best idea however, which means I should buy a book on WCF and start reading. Thanks again @Kevin. – Marko Nov 14 '10 at 20:54
1

Here goes another suggestion... If you`re using a DB, create a task (i.e. create a table that represents a task to be done) related with the messages that need to be sent and use Quartz.NET or similar (you may create a Windows Service too) that looks for incomplete tasks and executes them (marking them as done in case they are executed successfully).

uvita
  • 4,124
  • 1
  • 27
  • 23
  • I've gone with something similar but using the Windows Task Scheduler and a Console App that connects to my database. Your answer was the closest so I'll accept your one. – Marko Nov 14 '10 at 20:51
0

So my suggestion is to use ThreadPool. It would allow you to queue everything instead to run each of them separately, making it use less resource, but of course, taking longer to process everything, but like you said, time is not an issue.

Wildhorn
  • 926
  • 1
  • 11
  • 30
0

You could simply use the BackgroundWorker class.

The linked MSDN page has a nice example with progress reporting and possibility to cancel the operation.

Edit:
Progress reporting and cancellation might not be suitable in a web application, but the BackgroundWorker handles all the dirty stuff with creating a thread for you.

Edit2:
If you want to send many mails in parallel you can look the the Task Parallel Library.

Albin Sunnanbo
  • 46,430
  • 8
  • 69
  • 108
0

You could use Tasks to spawn off the worker thread to process the e-mails.

If this is hammering the CPU too much, you can create a new scheduler that reduces the concurrency: http://msdn.microsoft.com/en-us/library/ee789351.aspx

static void StartMailTasks(string[] addresses)
{
    List<Task> tasks = new List<Task>();
    foreach (var address in addresses)
    {
        tasks.Add(Task.Factory.StartNew(Email, address));
    }

    Task.Factory.ContinueWhenAll(tasks.ToArray(), AllDone, TaskContinuationOptions.OnlyOnRanToCompletion);
    Task.Factory.ContinueWhenAny(tasks.ToArray(), ReportError, TaskContinuationOptions.OnlyOnFaulted);
}

static void AllDone(Task[] tasks)
{
    // All is well
}

static void ReportError(Task errorTask)
{
    // Log or report the error
}

static void Email(object state )
{
    // send the e-mail  
    // Can throw error, if needed
}
Scott P
  • 3,775
  • 1
  • 24
  • 30