我如何调整这段代码以使用单个实例而不是创建服务的多个实例?



我正在编写一个发送电子邮件的服务,我想同时发送多个电子邮件通知。我现在看到的是:

private void SendInstantMailNotification(string notificationId)
{
MailMessage? message = null;
var notifications = _dbContext
.Notifications
.Where(x => x.Id.Equals(notificationId))
.ToList();
var notification = notifications.First();
message = notification.Content;
Smtp.SendMailSync(message, SmtpConfiguration, Smtp.MailTypeEnum.HTML);
}

代码的最后一行创建了"SMTP"服务。每次我想发送电子邮件时,都会创建一个新的实例。如何实现这一点,只有一个实例被创建和调用多次,而不会使系统过载?

这是构造函数:

private readonly NotificationQueueContext _dbContext;
protected NotificationQueueService(NotificationQueueContext dbContext)
{
_dbContext = dbContext;
}

据我所知,您需要一种按顺序运行某些任务的机制。因此,我创建了一个后台服务,它创建了一个SMTP client和一个ConcurrentQueue来保存邮件请求,并逐一运行它们。

此服务将在您的应用程序的整个过程中处于活动状态,因此它具有while(TRUE)。在发送每个电子邮件后,它等待500ms.

如果你想从其他服务发送邮件,你只需要调用RegisterMailRequest来排队邮件请求。

你应该像这样定义这个服务为HostedService:services.AddHostedService<SequentialJobHandler>();

using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using Microsoft.Extensions.Hosting;
using MimeKit;
namespace Sample
{
public class SequentialJobHandler : BackgroundService
{
private readonly string MailServerAddress;
private readonly int MailServerPort;
private readonly string AdminEmailAccount;
private readonly string AdminEmailAccountPass;
private readonly string MailUser;
private readonly string MailTitle;
private ConcurrentQueue<MailRequest> queue = new ConcurrentQueue<MailRequest>();

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var client = new SmtpClient())
{
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
await client.ConnectAsync(MailServerAddress, MailServerPort, MailKit.Security.SecureSocketOptions.Auto);
// Note: only needed if the SMTP server requires authentication
await client.AuthenticateAsync(MailUser, AdminEmailAccountPass);

while (true)
{
MailRequest localValue = null;
if (queue.TryDequeue(out localValue))
{
if (localValue != null)
{
SendMail(localValue, client);    
}
}
Thread.Sleep(500);
}
//await client.DisconnectAsync(true);
}
}

private async Task SendMail(MailRequest request, SmtpClient client)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress(MailTitle, AdminEmailAccount));
message.To.Add(new MailboxAddress(request.toUsername,  request.toEmail));
message.Subject = request.subject;
message.Body = new TextPart("html")
{
Text = request.body
};

await client.SendAsync(message);
}

public void RegisterMailRequest(MailRequest request)
{
queue.Enqueue(request);
}

public class MailRequest
{
public string toUsername, toEmail, subject, body;
}
}
}

希望对你有帮助。

最新更新