发送异步电子邮件而无需等待.NET Core Web服务



我有一个WebService .NET CORE2,它具有发送电子邮件的某些方法。我使用smtpclient.sendemailasync

工作正常。
    public async Task<bool> SendEmailAsync(MailMessage email)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(emailFrom)) email.From = new MailAddress(emailFrom);
            using (SmtpClient client = getSMTPClientInstance())
            {
                await client.SendMailAsync(email);
            }
            return true;
        }
        catch (Exception ex)
        {
            Log.Error(ex, "Error sending email in EmailService.SendEmailAsync");
            return false;
        }
    }

唯一的问题是,某些SMTP服务器需要太长的时间来响应。我想设置电子邮件,排队并返回而不等待结果。

仅使用未知的async出现两个原因;

  1. 在ASP

  2. 中继续使用请求上下文之外的方法是不可靠的。
  3. 我需要访问我实体框架的数据库上下文来编写日志

我必须允许外部或内部SMTP(我的客户指定),因此收集文件夹不是可能性 - 至少不是没有管理它的服务。

我该如何实现?我需要写一个管理此服务的服务吗?如果是这样,我将如何在.NET Core应用程序中执行此操作,请记住,该服务还需要访问EF上下文以编写日志

update

.netcore di中有管道可用,尤其是为此。请参阅下面的其他答案。使用IservicesCopeFactory

您可以在页面对象上调用RegisterAsyncTask方法。这将为您要确保在终止请求上下文之前确保完成的ASP.NET运行时发出信号:

示例:

public void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(LoadSomeData));
}
public async Task LoadSomeData()
{
    var clientcontacts = Client.DownloadStringTaskAsync("api/contacts");
    var clienttemperature = Client.DownloadStringTaskAsync("api/temperature");
    var clientlocation = Client.DownloadStringTaskAsync("api/location");
    await Task.WhenAll(clientcontacts, clienttemperature, clientlocation);
    var contacts = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Contact>>(await clientcontacts);
    var location = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clientlocation);
    var temperature = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(await clienttemperature);
    listcontacts.DataSource = contacts;
    listcontacts.DataBind();
    Temparature.Text = temperature;
    Location.Text = location;
}

https://www.hanselman.com/blog/themagicofusingasynchronousmethodsinaspnet45plusanimportantgotcha.aspx

因此,虽然我标记了答案,但对于我的特定示例来说,有一些选择是更好的解决方案。首先是使用诸如hangfire之类的库来安排任务的选项 - 尽管从技术上讲这不是问题的答案。

.net核心中更好的解决方案是使用iservicesCopeFactory

使用IservicesCopeFactory,您可以重新纠正一个任务,因此请求完成后它不会超出范围。我直接在控制器中进行了以下操作(后来我使用hangfire方法,但这可以使用)。如您所见,在控制器代码继续时,异步任务将在新的未知线程中发射。

        var task = Task.Run(async () =>
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var service = scope.ServiceProvider.GetRequiredService<ApprovalService>();
                await service.sendResponseEmailAsync(approvalInfo.ApprovalId, userID, approvalInfo.emailTo, approvalInfo.ccTo);
            }
        });

相关内容

  • 没有找到相关文章

最新更新