如何在 void 方法中使用异步
How can I use async in void method
我正在开发 Asp.Net 核心 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();
}
}
感谢任何帮助。
您可以将任务设置为您的方法的 return 类型:
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();
}
}
使用这种方法,您必须更改此方法的调用方以等待它。
我正在开发 Asp.Net 核心 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();
}
}
感谢任何帮助。
您可以将任务设置为您的方法的 return 类型:
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();
}
}
使用这种方法,您必须更改此方法的调用方以等待它。