我对使用后台任务通过.NET核心Web API发送计划的电子邮件的方式进行了过多的研究。我知道最好在与应用程序域单独运行的Windows服务中实施后台任务。
但是我的要求是从Web客户端获取的,每行都有一个表,这是针对客户的促销活动,我可以选择激活,暂停,停止每个客户,然后从这里调用API。
我必须为每个可以同步运行的后台任务实现每个后台任务。我必须通过Web API来执行此操作,因为最终用户没有托管服务的地方。
实际解决方案:
一天后,我想出了一种解决方案,该解决方案使用IHostedService
和BlockingCollection
来控制运行时的后台任务,如下所示:
使用IHostedService进行后台任务的代码:
namespace SimCard.API.Worker
{
internal class TimedHostedService : IHostedService, IDisposable
{
private CancellationTokenSource _tokenSource;
private readonly ILogger _logger;
private Timer _timer;
private readonly TasksToRun tasks;
private readonly IEmailService emailService;
public TimedHostedService(ILogger<TimedHostedService> logger, TasksToRun tasks, IEmailService emailService)
{
this.emailService = emailService;
this.tasks = tasks;
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
tasks.Dequeue();
_logger.LogInformation("Timed Background Service is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private void DoWork(object state)
{
emailService.SendEmail("ptkhuong96@gmail.com", "Test", "OK, Done now");
_logger.LogInformation("Mail sent!");
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}
这是BlockingCollection的代码:
namespace SimCard.API.Worker
{
public class TasksToRun : ITasksToRun
{
private readonly BlockingCollection<int> _tasks;
public TasksToRun() => _tasks = new BlockingCollection<int>();
public void Enqueue(int settings) => _tasks.Add(settings);
public void Dequeue() => _tasks.Take();
}
}
然后从Web客户端调用控制器中的代码:
[HttpPost("/api/worker/start")]
public IActionResult Run()
{
tasks.Enqueue(15);
return Ok();
}
Startup.cs的代码:
services.AddHostedService<TimedHostedService>();
services.AddSingleton<TasksToRun, TasksToRun>();
问题:
我真的满足于此要求,并且不知道如何进一步进行。如果您有其他方法可以适应我的情况,也可以推荐我。
非常感谢您的支持。