ニュースレターを受け取るメンバーを指定できるニュースレターシステムを作成しました。次に、基準を満たすメンバーのリストをループし、メンバーごとにパーソナライズされたメッセージを生成し、電子メールを非同期で送信します。部分的な作業は2回(ThreadPool.QueueUserWorkItem)
メールを送信するときは、ThreadPool.QueueUserWorkItem
を使用しています。
何らかの理由で、メンバーの一部が電子メールを2回受け取っています。私の最後のバッチでは、私は712人のメンバーにしか送っていませんでしたが、合計798のメッセージが送られてきました。
私は送信されたメッセージをログに記録しており、最初の86人のメンバーがメッセージを2度受信したことがわかりました。ここでは、メンバー163992は、メッセージ#1と#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
(メッセージが送信された順に)ログがあります。メンバー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));
}
私は競合状態に似ています - キューを使用する場合、ThreadPool.QueueUserWorkItem()を呼び出す前にキューから項目を削除しますか?あなたのコードを見ることができますか? – alexm
私は他の種類のキューを使用していません。基本的に:要件を満たすメンバーのリストをループし、メンバーの電子メールを生成し、実際にThreadPoolに電子メールを送信するメソッドへの呼び出しを追加します。 –
重複を避けるために、保留中の電子メールを持つユーザのリストを維持する – alexm