c# - 部分工作完成两次(ThreadPool.QueueUserWorkItem)

标签 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

然而,每个成员都应该收到一次时事通讯,正如您所见,成员 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));
    }

最佳答案

您确定您正在运行的用于获取要向其发送电子邮件的成员列表的查询中没有重复项吗?您要加入另一张 table 吗?你可以做的是:

List<DomainObjects.Members.MemberEmailNotificationInfo> list = GetListFromDatabase();
list = list.Distinct().ToList();

关于c# - 部分工作完成两次(ThreadPool.QueueUserWorkItem),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9626926/

相关文章:

c# - 展开集合并保存一些字段。

c# - 在 asp.net mvc4 应用程序中向 HtmlHelper 添加扩展方法

asp.net - 在 ASP.NET MVC 中,如何使用 C# 代码中的 Razor @Url.Content() 帮助程序?

c# - 如何告诉线程池在 `STA` 线程上运行委托(delegate)?

c# - 在 Xamarin 表单中加载 View 内容时显示事件指示器

c# - 从 Google 选择并下载随机图片

c# - 使用 List<T> 动态填充 asp.net Gridview

c# - ASP.NET 禁用基于另一个下拉列表值的下拉列表

java - 为什么 Scala 构建自己的 ForkJoinPool 而不是使用 java.util.concurrent.ForkJoinPool#commonPool?

java - 线程模板