2010-11-09 78 views
0

我有一个应用程序,其中一个动作触发了一些电子邮件发送出去。电子邮件的数量是可变的,可以是从10到1,000的任何地方每个动作在后台发送大量电子邮件 - 创建线程或使用ThreadPool?

我不希望应用程序挂起而邮件正在发送(因此恼人的用户),并希望在后台发送它们。

我以前没有使用线程,所以这就是为什么我需要你的帮助。你会手动创建线程吗?或者这是使用ThreadPool的好例子吗?我希望这项任务的优先级较低,并尽可能使用最少的资源,因为即使电子邮件迟了一个小时,我也不介意。

感谢您的帮助
马尔科

回答

1

这里如果你`重新使用DB去另一个建议... ,创建与需要发送的消息相关的任务(即创建一个表示要完成的任务的表),并使用Quartz.NET或类似的命令(您也可以创建Windows服务),查找不完整的任务并执行它们(将它们标记为完成以防它们被成功执行)。

+0

我已经走了类似的东西,但使用Windows任务计划程序和连接到我的数据库的控制台应用程序。你的答案是最接近的,所以我会接受你的答案。 – Marko 2010-11-14 20:51:35

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?

+0

谢谢@Kevin,绝对听起来很有希望。对C#4.0的TaskParallel库有什么想法?我没有使用WCF服务,因此我可能需要一些时间来实现您的解决方案。 – Marko 2010-11-09 21:17:32

+0

任务并行库非常简洁,但个人而言,如果你不关心完成需要多长时间,我会避免它。在不需要它的项目中引入外部复杂性毫无意义。如果你想消除我提到的线程问题,任务库不会绕过它。我会找到一些启动WCF的例子。 – kemiller2002 2010-11-09 21:23:21

+0

您的解决方案似乎是最好的解决方案,但是我缺乏WCF的经验意味着我不得不花费大量时间来开发它,并可能在最初几次出错。然而,解决方案似乎是最好的主意,这意味着我应该购买一本关于WCF的书并开始阅读。再次感谢@凯文。 – Marko 2010-11-14 20:54:04

0

你可以简单地使用BackgroundWorker类。

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

编辑:
进展报告和消除可能不适合于Web应用程序,但BackgroundWorker的处理所有的脏东西与你创建一个线程。

EDIT2:
如果你想发送许多并行的邮件,你可以看看的Task Parallel Library

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 
} 
相关问题