[英]WCF Service - queue & batch messages (sending emails via SMTP)
I have a WCF Service working via named pipes that is receiving data from ASP.NET MVC application: 我有一个WCF服务通过命名管道工作,该管道从ASP.NET MVC应用程序接收数据:
[ServiceContract]
public interface IEmailProcessor
{
[OperationContract(AsyncPattern = true)]
void SendEmails(string subject, string body, string from, string to);
}
Service gets subject, body, sender and recipients of an email. 服务获取电子邮件的主题,正文,发件人和收件人。 Then it puts an email together and send via SMTP.
然后将电子邮件放在一起并通过SMTP发送。
Client (MVC applicataion) is sending several emails at once, so I would like the service itself to work asynchronously (client just invokes SendEmails
method few times and then the WCF Server takes care of the rest). 客户端(MVC应用程序)一次发送几封电子邮件,因此我希望服务本身能够异步工作(客户端只需多次调用
SendEmails
方法,然后WCF Server会处理其余部分)。 But my email server sometimes refuses to send email because of greylisting of new email addresses. 但是我的电子邮件服务器有时会因为新电子邮件地址的灰名单而拒绝发送电子邮件。 That's why I would like the WCF Server to also queue those email and try to send them one by one (retry few times if the error occurs).
这就是为什么我希望WCF服务器也将那些电子邮件排队,并尝试将它们一一发送(如果发生错误,请重试几次)。
I've read several topics on WCF async nad MSMQ methods, but what is the best approach in my situation? 我已经阅读了关于WCF异步和MSMQ方法的几个主题,但是在我所处的情况下最好的方法是什么? Should I create two WCF Services (client-server & server-server)?
我是否应该创建两个WCF服务(客户端服务器和服务器服务器)? Or maybe use multi-threading?
或者也许使用多线程? It's also important for me to not use any built-in SMTP solution because I would like to expand my Service to handle other messages not only emails.
对于我来说,不要使用任何内置的SMTP解决方案也很重要,因为我想扩展我的服务以处理其他消息,而不仅仅是电子邮件。
For exactly the same requirement I've made this whole Email solution for my self however I did not use the MSMQ queue. 出于完全相同的要求,我为自己制作了整个电子邮件解决方案,但是我没有使用MSMQ队列。
following are the steps 以下是步骤
create a simple windows task scheduler task to invoke to run service on scheduled time period to retry sending emails Simple Window Task Schedular 创建一个简单的Windows任务调度任务调用运行在预定的时间周期的服务重新尝试发送邮件简单的窗口工作程序器
To read no deliver, failure email Emails from your exchange account I used third party service component Admin System Software and update table fields isDelivered=No , ErrorDescription=errorDesc 要读取不发送,失败的电子邮件从您的交换帐户发送的电子邮件,我使用了第三方服务组件“ 管理系统软件”,并且更新了表字段isDelivered = No,ErrorDescription = errorDesc
Hope this solution helps you.. 希望此解决方案对您有所帮助。
I followed zaitsman's suggestion and created queue inside the service using ConcurrentQueue
. 我遵循zaitsman的建议,并使用
ConcurrentQueue
在服务内部创建了队列。 I also used this example of creating new Thread: http://msdn.microsoft.com/en-us/library/7a2f3ay4%28v=vs.80%29.aspx 我还使用了创建新线程的示例: http : //msdn.microsoft.com/zh-cn/library/7a2f3ay4%28v=vs.80%29.aspx
I added new Thread to my WCF Server: 我向WCF服务器添加了新线程:
var thread = new Thread(EmailThread.Instace.DoWork);
thread.Start();
And then SendEmails method in my Service uses Enqueue
to add msg to the ConcurrentQueue
. 然后我的服务中的SendEmails方法使用
Enqueue
将msg添加到ConcurrentQueue
。
public void SendEmails(string from, string to, string subject, string body)
{
var msg = new MailMessage(from, to, subject, body)
{
IsBodyHtml = true,
BodyEncoding = Encoding.UTF8,
DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure
};
EmailThread.Instace.Messages.Enqueue(msg);
}
And here is EmailThread class that is doing it's work in the background (ie. accepting new emails to the queue and sequentially dequeuing them. 这是在后台执行工作的EmailThread类(即,将新的电子邮件接收到队列中并依次将它们出队)。
internal class EmailThread
{
//Ensure that only one instance of EmailThread can exist
private static readonly EmailThread Instance = new EmailThread();
public static EmailThread Instace { get { return Instance; } }
//Here is our Queue
public ConcurrentQueue<MailMessage> Messages { get; private set; }
private EmailThread()
{
Messages = new ConcurrentQueue<MailMessage>();
}
// This method is called when the thread is started and repeated once a 10 seconds
public void DoWork()
{
while (!_shouldStop)
{
Console.WriteLine("email sender thread: working...");
if (!Messages.IsEmpty)
{
//define SMTP credentials here
var smtp = new SmtpClient()
var failed = new Queue<MailMessage>();
MailMessage message;
while (Messages.TryDequeue(out message))
{
try
{
smtp.Send(message);
Console.WriteLine("email sender thread: successfully sent email...");
}
catch (SmtpException)
{
//Enqueue again if failed
failed.Enqueue(message);
Console.WriteLine("email sender thread: error sending email, enqueuing...");
}
}
foreach (var mailMessage in failed)
{
Messages.Enqueue(mailMessage);
}
smtp.Dispose();
}
Thread.Sleep(10000);
}
Console.WriteLine("email sender thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile is used as hint to the compiler that this data
// member will be accessed by multiple threads.
private volatile bool _shouldStop;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.