多线程Win Form应用程序的设计模型和提示

时间:2011-07-03 19:46:40

标签: c# winforms multithreading threadpool task

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

我公平地阅读了有关多线程应用程序的文章。我还阅读了有关SmartThread池,.NET ThreadPool,任务并行库和其他SO问题的内容。但我无法提供正确的设计。我的逻辑就是这样:

在程序开始时(电子邮件引擎),计时器启动并检查数据库(广告系列表)中是否有任何具有状态1(新广告系列)的电子邮件广告系列。

如果有,则应从数据库中查询Campaign订阅者,并将其写入名为SubscriberReports表的另一个表(SqlBulkCopy),并在Campaignigns表中将Campaign的状态更新为2.

计时器还会侦听状态为2的广告系列,以调用另一种方法为每个订阅者自定义广告系列,创建一个具有订阅者自定义属性的Struct。

第三,调用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.
 }

1 个答案:

答案 0 :(得分:3)

使用线程在这里几乎无法获得。什么线程给你买的是更多的cpu周期。假设您拥有一台具有多个内核的计算机,这些天非常标准。但这并不是你需要更快地完成工作所需要的。您需要更多dbase和电子邮件服务器。当然你只有一个。您的程序将刻录非常小核心,它会不断等待dbase查询和电子邮件服务器完成其工作。

获得成功的唯一方法是重叠每个的延迟。一个线程可能一直在等待dbase引擎,另一个线程可能一直在等待电子邮件服务器。哪个比等待两者的线程更好。

不过,这也不太可能让你买得太多,两者之间存在很大的不匹配。 dbase引擎可以在一秒钟内为您提供数千个电子邮件地址,电子邮件服务器每秒只能发送几百封电子邮件。一切都受到电子邮件服务器工作速度的限制。

鉴于获得成功的可能性很小,我建议你不要试图让线程陷入困境。如果你没有正确锁定,它有一个很难诊断失败的诀窍。您可以花费大量时间进行故障排除,这可能会大大超过移动速度的操作收益。

如果您正在考虑线程以避免冻结用户界面,那么这是合理的线程使用。使用BackgroundWorker。 MSDN Library对它有很好的帮助。