And*_*NET 8 c# asp.net threadpool
我创建了一个时事通讯系统,允许我指定哪些成员应该收到时事通讯.然后,我遍历符合条件的成员列表,并为每个成员生成个性化消息并异步发送电子邮件.
当我发送电子邮件时,我正在使用ThreadPool.QueueUserWorkItem.
出于某种原因,一部分成员正在收到两次电子邮件.在我的最后一批中,我只发送给712名成员,但总共发送了798封邮件.
我正在记录发出的消息,我能够告诉前86位成员收到消息两次.这是日志(按消息发送的顺序)
No. Member Date
1. 163992 3/8/2012 12:28:13 PM
2. 163993 3/8/2012 12:28:13 PM
...
85. 164469 3/8/2012 12:28:37 PM
86. 163992 3/8/2012 12:28:44 PM
87. 163993 3/8/2012 12:28:44 PM
...
798. 167691 3/8/2012 12:32:36 PM
Run Code Online (Sandbox Code Playgroud)
但是,每个成员都应该收到一次新闻通讯,因为您可以看到成员163992收到消息#1和#86; 成员163993收到消息#2和#87; 等等.
另一件需要注意的是,在发送消息#85和#86之间有7秒的延迟.
我已经多次查看过该代码并排除了几乎所有的代码都是它的原因,除了可能的ThreadPool.QueueUserWorkItem.
这是我第一次使用ThreadPool,所以我对它并不熟悉.是否有可能产生某种导致这种行为的竞争条件?
=== ---代码示例--- ===
foreach (var recipient in recipientsToEmail)
{
_emailSender.SendMemberRegistrationActivationReminder(eventArgs.Newsletter, eventArgs.RecipientNotificationInfo, previewEmail: string.Empty);
}
public void SendMemberRegistrationActivationReminder(DomainObjects.Newsletters.Newsletter newsletter, DomainObjects.Members.MemberEmailNotificationInfo recipient, string previewEmail)
{
//Build message here .....
//Send the message
this.SendEmailAsync(fromAddress: _settings.WebmasterEmail,
toAddress: previewEmail.IsEmailFormat()
? previewEmail
: recipientNotificationInfo.Email,
subject: emailSubject,
body: completeMessageBody,
memberId: previewEmail.IsEmailFormat()
? null //if this is a preview message, do not mark it as being sent to this member
: (int?)recipientNotificationInfo.RecipientMemberPhotoInfo.Id,
newsletterId: newsletter.Id,
newsletterTypeId: newsletter.NewsletterTypeId,
utmCampaign: utmCampaign,
languageCode: recipientNotificationInfo.LanguageCode);
}
private void SendEmailAsync(string fromAddress, string toAddress, string subject, MultiPartMessageBody body, int? memberId, string utmCampaign, string languageCode, int? newsletterId = null, DomainObjects.Newsletters.NewsletterTypeEnum? newsletterTypeId = null)
{
var urlHelper = UrlHelper();
var viewOnlineUrlFormat = urlHelper.RouteUrl("UtilityEmailRead", new { msgid = "msgid", hash = "hash" });
ThreadPool.QueueUserWorkItem(state => SendEmail(fromAddress, toAddress, subject, body, memberId, newsletterId, newsletterTypeId, utmCampaign, viewOnlineUrlFormat, languageCode));
}
Run Code Online (Sandbox Code Playgroud)
在服务器上运行 800 多个线程并不是一个好的做法!尽管您使用的是线程池,但线程会在服务器上排队,并在旧线程返回池并释放资源时运行。这可能在服务器上需要几分钟的时间,并且在此期间可能会发生许多情况,例如竞争条件或并发。您可以改为在一个受保护的列表上对一项工作项进行排队:
lock (recipientsToEmail)
{
ThreadPool.QueueUserWorkItem(t =>
{
// enumerate recipientsToEmail and send email
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1050 次 |
| 最近记录: |