如何使IHostingService在订单确认时发送电子邮件?

时间:2020-10-05 08:04:59

标签: c#

我有一个ac#WebApi项目,用户可以在该项目中在网站上下订单,付款完成后,每个订单都将执行一个名为ConfirmOrder的功能,该功能会将订单状态从STB更新为{{ 1}}。

在如下所示的函数中:

COMPLETED

我正在调用另一个函数public static void ConfirmOrder(string piva, string orderID, double importo = 0, string transazione = "", string paymentID = "", string tipo = "MENU") { string connectionString = getConnectionString(piva); using var connection = new MySqlConnection(connectionString); string query_menu = "QUERY"; string query_pagamenti = "QUERY"; using var cmd = new MySqlCommand(query_pagamenti, connection); connection.Open(); cmd.Parameters.AddWithValue("@tipo", tipo.ToUpper()); cmd.Parameters.AddWithValue("@importo", importo); cmd.Parameters.AddWithValue("@transazione", transazione); cmd.Parameters.AddWithValue("@dataOra", DateTime.Now); cmd.Parameters.AddWithValue("@orderID", orderID); cmd.Parameters.AddWithValue("@paymentID", paymentID); cmd.Prepare(); cmd.ExecuteNonQuery(); cmd.CommandText = query_menu; cmd.ExecuteNonQuery(); if (!tipo.Equals("MENU")) { EmailHelper.SendRiepilogo(piva, int.Parse(orderID)); // SENDING SUMMARY MAIL } } ,该函数将摘要发送给用户和商店,但是在这种情况下,我不能等待该函数响应,但是必须自己执行,而不会卡住{ {1}}回调..因此,我迫不及待要执行SendRiepilogo,目前我已经阅读了ConfirmOrder,但是我不知道该如何迁移我的SendRiepilogoIHostingService,然后从SendRiepilogo ...

运行

我的IHostingService看起来像这样:

ConfirmOrder

1 个答案:

答案 0 :(得分:2)

后台(托管)服务是完全服务,它使用自己的线程来完成其工作。您不能让控制器在该服务上“运行”某些东西,而必须告诉它要做什么,然后让它去做。

文档中的Background tasks with hosted services部分展示了长期运行的后台服务可以工作的两种不同方式:

  • 只要应用程序正在运行,定时服务就可以在每次触发计时器时运行并执行定期的工作
  • queued service在队列中等待消息,并在消息到达时执行工作

发送电子邮件适合第二种情况。您可以按原样使用文档示例。您可以创建一个IBackgroundTaskQueue界面,客户端(如控制器)可以用来提交作业以在后台运行:

public interface IBackgroundTaskQueue
{
    void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);

    Task<Func<CancellationToken, Task>> DequeueAsync(
        CancellationToken cancellationToken);
}

此接口可以作为依赖项添加到容器的构造函数中。 假设注入的服务称为myJobQueue,则控制器可以使用以下命令将作业加入后台运行:


IBackgroundTaskQueue _myJobQueue

public MyController(IBackgroundTaskQueue myJobQueue)
{
    _myJobQueue=myJobQueue;
}


public void ConfirmOrder(...)
{
    ...
    if (!tipo.Equals("MENU"))
    {
        var ordId=int.Parse(orderID);
    
  
  _myJobQueue.QueueBackgroundWorkItem(ct=>EmailHelper.SendRiepilogoAsync(piva,ordId )); 
}

async void仅应用于异步事件处理程序。那不是SendRiepilogo的意思。 async void方法无法等待,因为它们本质上是一劳永逸的方法,可能永远不会运行,因为应用程序不知道必须等待它们。 正确语法应为:

public static async Task SendRiepilogoAsync(string piva, int idOrdine)
{
...
}

文档示例的其余部分可以按原样使用。

简化服务

您可以创建一个仅接受特定消息类,仅接收地址和订单ID并让 service 进行检索的队列,而不是运行任何可用任务的常规队列服务。任何数据并发送电子邮件。本质上,SendRiepilogoAsync成为后台服务的一部分。这样就可以创建服务,例如批量处理电子邮件,同时发送多封电子邮件,应用限制等。

这将允许重用昂贵的资源或仅执行一次昂贵的操作,例如创建SmptClient并在开始处理队列消息之前进行身份验证