首页 > 解决方案 > 如何在 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();
    }
}

任何帮助表示赞赏。

标签: c#asp.net-coreasync-awaithangfire

解决方案


您可以将 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();
    }
}

使用这种方法,您必须更改此方法的调用者以等待它。


推荐阅读