【发布时间】:2011-03-10 18:01:39
【问题描述】:
我正在开发一个发送大量电子邮件的多线程异步表单应用程序。 我几乎完成了应用程序,但对性能感到担忧。如果您用更好的最佳实践启发我,那将是完美的,我将真正学习基础知识,因为我是一名初级开发人员。
这是一个问题: 首先,我有触发 Windows.Forms.Timer 组件的应用程序的“开始”按钮。
private void btnStart_MouseClick(object sender, MouseEventArgs e)
{
timerNewCampaignChecker.Tick += new EventHandler(timerNewCampaignChecker_Tick);
timerNewCampaignChecker.Enabled = true;
timerNewCampaignChecker.Start();
}
应用程序需要每 3 秒检查一次数据库是否有新的广告系列(第一种方法),自定义广告系列详细信息(第 2 种方法)内嵌到用户输入,并通过电子邮件将广告系列发送给接收者(第三种方法)。 为了每 3 秒检查一次数据库中的新广告系列,我有上述计时器(间隔为 3 秒),它通过检查新广告系列来启动流程:
MethodInvoker invoker;
private void timerNewCampaignChecker_Tick(object sender, EventArgs e)
{
invoker = new MethodInvoker(CheckNewCampaigns);
invoker.BeginInvoke(null, null);
}
因此,计时器每 3 秒触发一次 CheckNewCampaigns 方法,让流程从第一步开始。 从计时器本身启动流程和线程池结构是否正确??? 现在 CheckNewCampaigns 检查 DB,创建一个 List 对象,并且对于每个活动,它将对象的详细信息发送到另一个方法通过调用 ThreadPool。
delegate bool StepCaller(int campaignID);
private void CheckNewCampaigns()
{
StringBuilder builder = new StringBuilder();
StepCaller stepCaller = new StepCaller(PrepareCampaignEmail);
IEnumerable<Campaigns> CampaignsList = DatabaseManager.GetCampaignsList(DatabaseManager.GetNewCampaigns());
foreach (Campaigns Campaign in CampaignsList)
{
stepCaller.BeginInvoke(Campaign.CampaignID, new AsyncCallback(PrepareEmailCallback), null);
}
}
我必须在第一种方法中编写 endInvoke 代码,还是应该直接触发并忘记??。因为最重要的是应用程序有一个流程,参数在方法之间传递,第二个方法应该知道第一个何时完成,以便它可以获取活动ID并自定义它。但是在执行这些操作时,应该启动一个新流程并检查第一种方法的新活动。并且电子邮件也应该同时发送。 新方法(第二个)自定义活动并通过使用 ThreadPool 调用另一个方法(第三个)。 这里是:
private bool PrepareCampaignEmail(int campaignID)
{
EmailCaller emailCaller = new EmailCaller(SendEmail);
IEnumerable<Subscribers> SubscribersList = DatabaseManager.GetCampaignSubscribersList(DatabaseManager.GetCampaignSubscribers(campaignID));
CampaignCustomazition campaignCustomizer;
List<CampaignCustomazition> campaignCustomizedList = new List<CampaignCustomazition>(); // foreach in içindeki beginInvoke ı dışarıya çıkardığımda kullanılacak
foreach (Subscribers subscriber in SubscribersList)
{
campaignCustomizer = new CampaignCustomazition(campaignID);
campaignCustomizer.CustomizeSource(campaignID, out campaignCustomizer.source, out campaignCustomizer.format);
campaignCustomizer.CustomizeCampaignDetails(campaignID, out campaignCustomizer.subject, out campaignCustomizer.fromName, out campaignCustomizer.fromEmail, out campaignCustomizer.replyEmail);
campaignCustomizer.CustomizeSubscriberDetails(campaignID, out campaignCustomizer.subscriberID, out campaignCustomizer.email, out campaignCustomizer.fullName);
IAsyncResult result = emailCaller.BeginInvoke(campaignCustomizer, null, null);
try
{
emailCaller.EndInvoke(result);
}
catch(Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
return false;
}
我猜这第二步有一个主要问题。数据库操作将近5-6次。这可能是线程的问题。它似乎工作正常,但我的方式可能是错误的。一天可以有几十个活动。这是一个问题,还是我的方式好吗?(顺便说一下,数据库操作没有那么苛刻和复杂)。
准备好邮件后,就可以发送上面调用的邮件了。第三种方法是一个简单的 SMTP 方法,它发送电子邮件并记录它。
最后一个方法也没有 EndInvoke 功能,但这是应用程序的最后一个方法,作为刚刚发送的邮件。
我处理定时器和线程池的方式在你看来合乎逻辑吗? 如何以最佳方式测试性能并优化线程池的工作? 对于上述任何一项,您有什么建议和教导?
非常感谢。
【问题讨论】:
-
嗯,不回答这个问题似乎会提高我收到更少垃圾邮件的几率。这很有吸引力。
-
一篇文章有很多问题...
-
粗略阅读后,我发现:一个 3 秒的计时器可以处理“一天数十个活动”。这似乎有点矫枉过正。尽管帖子很长,但我们不知道我们正在谈论多少电子邮件/小时,如何处理失败,......以及这是多么合法/垃圾邮件?运动一词表明汉斯可能有一个观点。
-
OP 的昵称解释了问题中使用的文本数量 :)
-
@Hans 发送大量电子邮件有很多正当理由,我严重怀疑垃圾邮件发送者是否需要咨询 StackOverflow 以获取有关如何有效发送电子邮件的帮助。
标签: c# multithreading timer threadpool