【问题标题】:Design Model and Hints For Multithreaded Win Form Application多线程 Win Form 应用程序的设计模型和提示
【发布时间】:2011-07-03 19:46:39
【问题描述】:

我正在尝试设计一个多线程的 windows 应用程序,主要是为我们的客户快速发送电子邮件给他们的客户(可能有数百万,因为有一家大型电信公司),我需要设计提示。(我很抱歉 Q很长)

我相当阅读有关多线程应用程序的文章。我还阅读了有关 SmartThread Pool、.NET ThreadPool、Task Parallel Library 和其他 SO 问题的信息。但我无法提供正确的设计。我的逻辑是这样的:

在程序启动时(电子邮件引擎),计时器启动并检查数据库(活动表)中是否有状态为 1(新活动)的电子邮件活动。

如果有,则应从 DB 中查询 Campaign 订阅者,并将其写入另一个名为 SubscriberReports 表的表 (SqlBulkCopy),并在 Campaigns 表中将 Campaign 的 Status 更新为 2。

Timer 还侦听状态为 2 的活动,以调用另一个方法为每个订阅者自定义活动,创建一个具有订阅者自定义属性的结构。

第三,调用 SendEmail 方法通过 SMTP 发送电子邮件。到目前为止我尝试的内容如下(我知道 ThreadPool 在这里是错误的,而且我还有很多其他错误)。您能否建议并帮助我如何设计这样的应用程序。非常感谢任何帮助。非常感谢您的宝贵时间。

private void ProcessTimer(object Source, ElapsedEventArgs e)
{
    Campaigns campaign = new Campaigns();
    IEnumerable<Campaigns> campaignsListStatusOne = // Get Campaign Properties to a List
    IEnumerable<Campaigns> campaignsListStatusTwo = // Get Campaign Properties to a List            

    foreach (Campaigns _campaign in campaignsListStatusOne)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(CheckNewCampaign), _campaign.CampaignID);
    }

    foreach (Campaigns _campaign in campaignsListStatusTwo)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(CustomizeMail), _campaign.CampaignID);
    }
}

private void CheckNewCampaign(object state)
{
    int campaignID = (int)state;
    DataTable dtCampaignSubscribers = // get subscribers based on Campaign ID
    campaign.UpdateStatus(campaignID, 2);
}

private void CustomizeMail(object state)
{
    int campaignID = (int)state;
    CampaignCustomazition campaignCustomizer;
    IEnumerable<SubscriberReports> reportList = // get subscribers to be sent from Reports table

    foreach (SubscriberReports report in reportList)
    {   // 3 database related methods are here
        campaignCustomizer = new CampaignCustomazition(report.CampaignID, report.SubscriberID);

        campaignCustomizer.CustomizeSource(report.CampaignID, report.SubscriberID, out campaignCustomizer.source, out campaignCustomizer.format);
        campaignCustomizer.CustomizeCampaignDetails(report.CampaignID, report.SubscriberID, out campaignCustomizer.subject, out campaignCustomizer.fromName, out campaignCustomizer.fromEmail, out campaignCustomizer.replyEmail);
        campaignCustomizer.CustomizeSubscriberDetails(report.SubscriberID, out campaignCustomizer.email, out campaignCustomizer.fullName);

        ThreadPool.QueueUserWorkItem(new WaitCallback(SendMail), campaignCustomizer);
    }
} 

private void SendMail(object state)
{
    CampaignCustomazition campaignCustomizer = new CampaignCustomazition();
    campaignCustomizer = (CampaignCustomazition)state;
    //send email based on info at campaignCustomizer via SMTP and update DB record if it is success.
 }

【问题讨论】:

  • 先尝试写应用单线程,然后看看性能是否足够好。如果不是,请考虑如何改进代码,例如将电子邮件写入放置目录而不是连接到 smtp 服务器。重写您对数据库的访问,获取批次而不是单个记录。并处理您的交易。

标签: c# winforms multithreading threadpool task


【解决方案1】:

使用线程在这里几乎没有什么收获。线程给你带来的是更多的 CPU 周期。假设您有一台具有多核的机器,这些天非常标准。但这不是您更快完成工作所需要的。您需要更多的 dbase 和电子邮件服务器。当然,您每个人都只有一个。你的程序会烧掉非常个小内核,它一直在等待 dbase 查询和电子邮件服务器完成它们的工作。

领先的唯一方法是重叠每个延迟。一个线程可能一直在等待 dbase 引擎,另一个可能一直在等待电子邮件服务器。这比一个线程同时等待两者要好。

不过,这也不太可能让你买太多,两者之间存在很大的不匹配。 dbase引擎可以在一秒钟内给你数千个电子邮件地址,电子邮件服务器在一秒钟内只能给你几百个电子邮件。一切都受到电子邮件服务器运行速度的限制。

鉴于取得成功的可能性很小,我建议您不要试图让自己在线程方面遇到麻烦。如果您没有正确锁定,它具有产生很难诊断故障的诀窍。您可以花在解决此问题上的时间远远超过移动速度稍微快一点所带来的运营收益。

如果您正在考虑使用线程来避免冻结用户界面,那么这是线程的合理用途。使用后台工作者。 MSDN 库对此有很好的帮助。

【讨论】:

  • 好吧,如果电子邮件服务器允许来自 OP 的多个连接,那么多线程客户端的执行速度将远远快于仅针对 TCP 三个-路/四路连接/断开协议的单线程客户端。线程给你带来的不仅仅是 CPU 周期——它们有助于以有效的方式应用你拥有的 CPU 周期。在允许多个连接的高速但高延迟网络的情况下,多线程电子邮件客户端在单核机器上的速度会大大提高。
  • @Hans,谢谢你的回答。但是,如果要同时发送多个广告系列怎么办。他们必须在到达时交付。我想,我无法用单线程发送它们。
  • 我看不出区别。这不就是另一个查询结果不同的查询吗?
  • @Hans,不,客户可能总是从 Web 界面创建电子邮件活动。引擎必须监听所有新来的并开始立即发送过程。顺便说一句,引擎现在可以在服务器上运行,而服务器只是让该引擎运行。邮件服务器也在那台机器上。服务器是 64 位的。
  • 如果服务器正在处理来自先前请求的 10000 封电子邮件的列表,那么您不太可能希望允许某人闯入并将他们的 100000 封电子邮件放在前面。优先级取决于您。
猜你喜欢
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多