Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程Win Form应用程序的设计模型和提示_C#_Winforms_Multithreading_Threadpool_Task - Fatal编程技术网

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

C# 多线程Win Form应用程序的设计模型和提示,c#,winforms,multithreading,threadpool,task,C#,Winforms,Multithreading,Threadpool,Task,我正在尝试设计一个多线程的windows应用程序,主要用于我们的客户快速向他们的客户发送电子邮件(可能有数百万,因为有一家大型电信公司),我需要设计提示。(很抱歉,Q很长) 我读了一些关于多线程应用程序的文章。我还阅读了有关SmartThreadPool、.NET ThreadPool、任务并行库和其他SO问题的文章。但我无法提供正确的设计。我的逻辑是这样的: 在程序启动(电子邮件引擎)内,计时器启动并检查数据库(活动表)中是否有状态为1(新活动)的电子邮件活动 如果存在,则应从DB查询活动订阅

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

我读了一些关于多线程应用程序的文章。我还阅读了有关SmartThreadPool、.NET ThreadPool、任务并行库和其他SO问题的文章。但我无法提供正确的设计。我的逻辑是这样的:

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

如果存在,则应从DB查询活动订阅者,并将其写入另一个名为SubscriberReports table的表(SqlBulkCopy),并将活动表中的活动状态更新为2

计时器还侦听状态为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.
 }
private void ProcessTimer(对象源,ElapsedEventArgs e)
{
活动活动=新活动();
IEnumerable campaignsListStatusOne=//获取列表中的活动属性
IEnumerable活动列表状态二=//将活动属性获取到列表中
foreach(活动-活动列表状态一中的活动)
{
ThreadPool.QueueUserWorkItem(新WaitCallback(CheckNewCampaign),\u campaign.CampaignID);
}
foreach(活动-活动列表状态2中的活动)
{
ThreadPool.QueueUserWorkItem(新的WaitCallback(自定义电子邮件),\u campaign.campaid);
}
}
私有void CheckNewCampaign(对象状态)
{
int活动ID=(int)状态;
DataTable dtCampaignSubscribers=//根据活动ID获取订阅服务器
campaign.UpdateStatus(活动ID,2);
}
专用电子邮件(对象状态)
{
int活动ID=(int)状态;
活动定制活动定制者;
IEnumerable reportList=//从报表表获取要发送的订阅服务器
foreach(报告列表中的SubscriberReports报告)
{//3与数据库相关的方法在这里
活动定制器=新的活动定制(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.ReplyMail);
campaignCustomizer.CustomizeSubscriberDetails(report.SubscriberID、out-campaignCustomizer.email、out-campaignCustomizer.fullName);
QueueUserWorkItem(新的WaitCallback(SendMail),活动自定义程序);
}
} 
私有void SendMail(对象状态)
{
活动定制活动定制者=新活动定制();
活动定制器=(活动定制)状态;
//根据活动定制器上的信息通过SMTP发送电子邮件,如果成功,则更新DB记录。
}

使用线程在这里几乎没有什么好处。线程给你带来的是更多的cpu周期。假设你有一台多核的机器,现在已经很标准了。但这并不是你更快完成工作所需要的。您需要更多的数据库和电子邮件服务器。当然,你每一个都只有一个。您的程序将消耗很少的内核,它一直在等待数据库查询和电子邮件服务器完成它们的工作

取得进展的唯一方法是重叠每个项目的延迟。一个线程可能一直在等待数据库引擎,另一个线程可能一直在等待电子邮件服务器。这比一个线程同时等待两个线程要好

不过,这也不太可能给你带来太多好处,两者之间存在很大的不匹配。数据库引擎可以在一秒钟内为您提供数千个电子邮件地址,而电子邮件服务器在一秒钟内只能提供几百封电子邮件。电子邮件服务器的工作速度限制了一切

考虑到获得成功的几率很低,我建议您不要试图让自己在线程方面陷入麻烦。它有一个诀窍,如果您没有正确锁定,它会产生非常难以诊断的故障。您花在故障排除上的时间可能会大大超过移动稍微快一点带来的操作收益


如果您正在考虑使用线程来避免冻结用户界面,那么这就是线程的合理用途。使用BackgroundWorker。MSDN库在这方面有很好的帮助。

使用线程在这里几乎没有什么好处。线程给你带来的是更多的cpu周期。假设你有一台多核的机器,现在已经很标准了。但这并不是你更快完成工作所需要的。您需要更多的数据库和电子邮件服务器。当然,你每一个都只有一个。您的程序将消耗很少的内核,它一直在等待数据库查询和电子邮件服务器完成它们的工作

取得进展的唯一方法是重叠每个项目的延迟。一个线程可能一直在等待数据库引擎,另一个线程可能一直在等待电子邮件服务器。这比一个线程同时等待两个线程要好

不过,这也不太可能给你带来太多好处,两者之间存在很大的不匹配。数据库引擎可以在一秒钟内为您提供数千个电子邮件地址,而电子邮件服务器在一秒钟内只能提供几百封电子邮件。电子邮件服务器的工作速度限制了一切

胃肠道