开发者

Sending mass emails in the background - Create Thread or use ThreadPool?

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 resourc开发者_如何学运维es possible because I don't mind even if the email is 1 hour late.

Appreciate your help

Marko


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?


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).


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.


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.


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
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜