我有一个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
,但是我不知道该如何迁移我的SendRiepilogo
到IHostingService
,然后从SendRiepilogo
...
我的IHostingService
看起来像这样:
ConfirmOrder
答案 0 :(得分:2)
后台(托管)服务是完全服务,它使用自己的线程来完成其工作。您不能让控制器在该服务上“运行”某些东西,而必须告诉它要做什么,然后让它去做。
文档中的Background tasks with hosted services部分展示了长期运行的后台服务可以工作的两种不同方式:
发送电子邮件适合第二种情况。您可以按原样使用文档示例。您可以创建一个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并在开始处理队列消息之前进行身份验证