在后台发送大量电子邮件 - 创建线程或使用ThreadPool?

时间:2010-11-09 20:42:44

标签: c# asp.net-mvc multithreading threadpool mass-emails

我有一个应用程序,其中一个动作触发了许多电子邮件发送出去。电子邮件的数量是可变的,每个操作可以是10到1,000

我不希望应用程序在发送电子邮件时挂起(从而使用户烦恼)并希望在后台发送它们。

我过去没有使用过Threads,这就是我需要你帮助的原因。你会手动创建线程还是使用ThreadPool的好例子?我希望此任务具有低优先级并尽可能少地使用资源,因为即使电子邮件迟到1小时我也不介意。

感谢您的帮助
马尔科

5 个答案:

答案 0 :(得分:3)

说实话,ASP.NET中的线程并不是一个好主意。当请求结束并回发给用户时,Asp.net会处理大量资源。由于您不希望用户等待,因此您将遇到这种情况,您认为可以安全使用的ASP.NET对象确实已经处理掉了。

您最好的选择是创建一个外部服务(在IIS中运行的wcf服务,或者暴露了wcf接口的Windows服务).net页面可以异步调用该服务,并在该请求完成之前运行该请求。不用担心线程等。它运行在它自己的进程中,当它完成时就完成了。由于您不关心告诉用户已完成,因此您不必担心它会进行通信。这样,如果你需要让其他一些页面使用相同的服务接口,就可以调用它。

关于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?

答案 1 :(得分:1)

这是另一个建议...... 如果您正在使用数据库,请创建一个任务(即创建一个表示要完成的任务的表)与需要发送的消息相关并使用Quartz.NET或类似的(您也可以创建一个Windows服务) )查找不完整的任务并执行它们(如果成功执行则将它们标记为已完成)。

答案 2 :(得分:0)

所以我的建议是使用ThreadPool。它允许你排队所有内容而不是分别运行它们,使它使用更少的资源,但当然,需要更长的时间来处理所有内容,但就像你说的那样,时间不是问题。

答案 3 :(得分:0)

您可以简单地使用BackgroundWorker类。

链接的MSDN页面有一个很好的例子,包括进度报告和取消操作的可能性。

修改
进度报告和取消可能不适合Web应用程序,但BackgroundWorker会为您创建一个线程来处理所有脏东西。

<强> EDIT2:
如果您想并行发送多封邮件,可以查看Task Parallel Library

答案 4 :(得分:0)

您可以使用“任务”来生成工作线程以处理电子邮件。

如果这对CPU造成太大影响,您可以创建一个新的调度程序来减少并发性: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
}