NOTE: Apart from
(and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.
Friday, 13 September 2024
//Less than a minute
一. 导言 一. 导言 一. 导言 一. 导言 一. 导言 一. 导言 一. 导言 一. 导言 一. 导言 一. 导言
使用流利电子邮件及SMTP客户端发送电子邮件。 然而,其中一个问题是电子邮件发送的延误。 SMTP服务器往往速度缓慢,可能需要一段时间才能发送电子邮件。 这可能会令用户感到烦恼,
其中一个办法就是在背景中发送邮件。 这样用户就可以继续使用应用程序而不必等待电子邮件发送。 这是网络应用程序中的一种常见模式,可以使用背景工作实现。
[技选委
在 ASP.NET Core 中,你有两个主要选项(除了更先进的选项,如Hangfire/Quartz)
在这个例子中,我将使用一个简单的 IHOSTD Service 来发送背景中的邮件。
完整的资料来源如下。
namespace Mostlylucid.Email
{
public class EmailSenderHostedService(EmailService emailService, ILogger
public async Task SendEmailAsync(BaseEmailModel message)
{
await _mailMessages.SendAsync(message);
}
public Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Starting background e-mail delivery");
// Start the background task
_sendTask = DeliverAsync(cancellationTokenSource.Token);
return Task.CompletedTask;
}
public async Task StopAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Stopping background e-mail delivery");
// Cancel the token to signal the background task to stop
await cancellationTokenSource.CancelAsync();
// Wait until the background task completes or the cancellation token triggers
await Task.WhenAny(_sendTask, Task.Delay(Timeout.Infinite, cancellationToken));
}
private async Task DeliverAsync(CancellationToken token)
{
logger.LogInformation("E-mail background delivery started");
while (!token.IsCancellationRequested)
{
BaseEmailModel? message = null;
try
{if(_mailMessages.Count == 0) continue;
message = await _mailMessages.ReceiveAsync(token);
switch (message)
{
case ContactEmailModel contactEmailModel:
await emailService.SendContactEmail(contactEmailModel);
break;
case CommentEmailModel commentEmailModel:
await emailService.SendCommentEmail(commentEmailModel);
break;
}
logger.LogInformation("Email from {SenderEmail} sent", message.SenderEmail);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception exc)
{
logger.LogError(exc, "Couldn't send an e-mail from {SenderEmail}", message?.SenderEmail);
await Task.Delay(1000, token); // Delay and respect the cancellation token
if (message != null)
{
await _mailMessages.SendAsync(message, token);
}
}
}
logger.LogInformation("E-mail background delivery stopped");
}
public void Dispose()
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
}
}
}
</details>
这里您可以看到我们处理服务的启动, 并设置一个新的 ButfferBlock 来控制电子邮件 。
```csharp
public class EmailSenderHostedService(EmailService emailService, ILogger<EmailSenderHostedService> logger)
: IHostedService, IDisposable
{
private readonly BufferBlock<BaseEmailModel> _mailMessages = new();
private Task _sendTask = Task.CompletedTask;
private CancellationTokenSource cancellationTokenSource = new();
我们还设立了一个新的任务,在背景中发送电子邮件。 以及取消源代码 当我们想停止服务时 优雅地取消任务。
然后我们用StartAsync启动托管服务, 并为其他服务发送电子邮件提供切入点。
public async Task SendEmailAsync(BaseEmailModel message)
{
await _mailMessages.SendAsync(message);
}
public Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Starting background e-mail delivery");
// Start the background task
_sendTask = DeliverAsync(cancellationTokenSource.Token);
return Task.CompletedTask;
}
在我们的设置类中,我们现在需要 注册服务 在DI集装箱 并启动主机服务
services.AddSingleton<EmailSenderHostedService>();
services.AddHostedService(provider => provider.GetRequiredService<EmailSenderHostedService>());
现在,我们可以通过在电子邮件SenderHosted Services上 调用SendeEmailAsync 方法, 在背景中发送电子邮件。 例如,对于联系表,我们这样做。
var contactModel = new ContactEmailModel()
{
SenderEmail = user.email,
SenderName =user.name,
Comment = commentHtml,
};
await sender.SendEmailAsync(contactModel);
在上文的代码中,这又增加了这一信息。 BufferBlock<BaseEmailModel>
_邮件邮件和背景任务将接收并发送电子邮件。
private async Task DeliverAsync(CancellationToken token)
{
...
while (!token.IsCancellationRequested)
{
BaseEmailModel? message = null;
try
{if(_mailMessages.Count == 0) continue;
message = await _mailMessages.ReceiveAsync(token);
switch (message)
{
case ContactEmailModel contactEmailModel:
await emailService.SendContactEmail(contactEmailModel);
break;
case CommentEmailModel commentEmailModel:
await emailService.SendCommentEmail(commentEmailModel);
break;
}
logger.LogInformation("Email from {SenderEmail} sent", message.SenderEmail);
...
}
logger.LogInformation("E-mail background delivery stopped");
}
这将循环, 直到我们停止服务, 并继续监视 ButfferBlock, 以便发送新的电子邮件 。