c# - 如何在 void 方法中使用异步
问题描述
我正在开发 Asp.Net Core MVC Web 应用程序,我必须每天检查任何用户的“EndOfSubscription”是否结束。我必须将所有用户设置为“已过期”,然后向该用户发送电子邮件。
整个过程应该作为后台任务来实现。现在,它每天都能成功运行,并将用户设置为“已过期”。但我的问题是如何在立即将用户设置为“过期”后发送电子邮件。由于我必须使用 (await) 发送电子邮件,但我知道将 (await) 用于 void 方法是一种不好的做法。我试图做扩展方法,但它没有按预期工作。
这是我的启动文件。
public void ConfigureServices(IServiceCollection services)
{
---------- Lines of Code ----------
services.AddSingleton<IEmailSender, EmailSender>();
services.Configure<EmailOptions>(Configuration);
services.AddHangfire(config => config.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));
services.AddHangfireServer();
services.AddScoped<IExpirationJob, ExpirationJob>();
}
public void Configure(IApplicationBuilder app,
IWebHostEnvironment env,
IRecurringJobManager recurringJobManager,
IServiceProvider serviceProvider)
{
---------- Lines of Code ----------
app.UseHangfireDashboard();
//app.UseHangfireDashboard("/hangfire", new DashboardOptions()
//{
// Authorization = new[] { new CustomAuthorizeFilter() }
//});
app.UseAuthentication();
app.UseAuthorization();
recurringJobManager.AddOrUpdate(
"End Users Subscription",
() => serviceProvider.GetService<IExpirationJob>().SetExpired(),
Cron.Minutely
);
}
}
}
这是 ExpiredUsersServices 文件
public interface IExpirationJob
{
void SetExpired();
}
public class ExpirationJob : IExpirationJob
{
private readonly ApplicationDbContext _db;
private readonly IEmailSender _emailSender;
public ExpirationJob(ApplicationDbContext db, IEmailSender emailSender)
{
_db = db;
_emailSender = emailSender;
}
public void SetExpired()
{
foreach(var item in _db.Institution)
{
if (item.EndOfSubscriptionDate <= DateTime.Today)
{
item.Status = SD.StatusExpired;
//await _emailSender.SendEmailAsync( item.Admin.Email, "Your Account is Expired !", "Your subscription is over and your account is expired.");
}
}
await _db.SaveChangesAsync();
}
}
任何帮助表示赞赏。
解决方案
您可以将 Task 设置为您的方法的返回类型:
public interface IExpirationJob
{
Task SetExpired();
}
public class ExpirationJob : IExpirationJob
{
private readonly ApplicationDbContext _db;
private readonly IEmailSender _emailSender;
public ExpirationJob(ApplicationDbContext db, IEmailSender emailSender)
{
_db = db;
_emailSender = emailSender;
}
public async Task SetExpired()
{
foreach(var item in _db.Institution)
{
if (item.EndOfSubscriptionDate <= DateTime.Today)
{
item.Status = SD.StatusExpired;
await _emailSender.SendEmailAsync( item.Admin.Email, "Your Account is Expired !", "Your subscription is over and your account is expired.");
}
}
await _db.SaveChangesAsync();
}
}
使用这种方法,您必须更改此方法的调用者以等待它。
推荐阅读
- javascript - 如果其中一个键相同,则收集数组下的数组元素
- python - 在python中创建一个不规则的锯齿函数
- haskell - Tuples 里面的 Tuples 类型不同还是相似?
- sql-server - 尝试查询 XML 数据 - 节点中有一个空格
- codeigniter-3 - GroceryCRUD 隐藏软删除记录
- angularjs - Karma+AngularJS - 结合模板和控制器
- ios - 当我尝试从 React Native iOS 应用程序共享我的应用程序 URL 时,应用程序变得无响应
- python - 为什么 python 不回收悬空线程?
- function - 函数中的 clearInterval
- java - 保持对象 onPause()