【问题标题】:Sending mass emails in the background - Create Thread or use ThreadPool?在后台发送大量电子邮件 - 创建线程还是使用线程池?
【发布时间】:2023-03-06 12:03:01
【问题描述】:

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

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

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

感谢您的帮助
Marko

【问题讨论】:

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


    【解决方案1】:

    说实话,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?

    【讨论】:

    • 感谢@Kevin,这听起来很有希望。你对 c# 4.0 的 TaskParallel 库有什么看法?我没有使用过 WCF 服务,因此我可能需要一些时间来实施您的解决方案。
    • 任务并行库非常简洁,但就个人而言,如果您不在乎需要多长时间才能完成,我会避免使用它。在不需要的项目中引入外部复杂性是没有意义的。如果您希望消除我谈到的线程问题,任务库将无法解决它。我也会为您找到一些启动 WCF 的示例。
    • 您的解决方案似乎是最好的解决方案,但我缺乏 WCF 经验,这意味着我必须花费大量时间来开发它,而且最初几次可能会出错。然而,这个解决方案似乎是最好的主意,这意味着我应该买一本关于 WCF 的书并开始阅读。再次感谢@Kevin。
    【解决方案2】:

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

    【讨论】:

    • 我使用了类似的东西,但使用了 Windows 任务计划程序和连接到我的数据库的控制台应用程序。你的答案是最接近的,所以我会接受你的。
    【解决方案3】:

    所以我的建议是使用线程池。它将允许您将所有内容排队,而不是单独运行它们中的每一个,从而使用更少的资源,但是当然,处理所有内容需要更长的时间,但正如您所说,时间不是问题。

    【讨论】:

      【解决方案4】:

      您可以简单地使用BackgroundWorker 类。

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

      编辑:
      进度报告和取消可能不适合 Web 应用程序,但 BackgroundWorker 会通过为您创建线程来处理所有脏东西。

      编辑2:
      如果您想并行发送多封邮件,您可以查看Task Parallel Library

      【讨论】:

        【解决方案5】:

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

        如果这对 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
        }
        

        【讨论】:

          猜你喜欢
          • 2012-03-29
          • 1970-01-01
          • 2014-09-02
          • 1970-01-01
          • 2011-04-07
          • 1970-01-01
          • 2017-10-23
          • 2018-09-22
          • 2015-01-18
          相关资源
          最近更新 更多