c# - 尝试使用 IBackgroundTaskQueue 时未设置对象引用
问题描述
我正在尝试在基于 .NET Core 的 c# WebApi 2 项目中使用 IHostingService。
IHostingService 应该通过 SMPT 在每个通过队列后台任务确认的订单上发送电子邮件,我正在关注Microsoft 文档和在另一个问题中建议这种方式的用户的回答,问题是当我尝试运行 _taskQueue 我得到以下错误:
System.NullReferenceException:“对象引用未设置为对象的实例。”
虽然我无法理解我必须如何正确启动 IBackgroundTaskQueue 才能正确运行任务而不会出现 null ref 错误......
我的代码如下所示:
背景任务队列.cs:
public interface IBackgroundTaskQueue
{
void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem);
Task<Func<CancellationToken, Task>> DequeueAsync(
CancellationToken cancellationToken);
}
public class BackgroundTaskQueue : IBackgroundTaskQueue
{
private ConcurrentQueue<Func<CancellationToken, Task>> _workItems =
new ConcurrentQueue<Func<CancellationToken, Task>>();
private SemaphoreSlim _signal = new SemaphoreSlim(0);
public void QueueBackgroundWorkItem(
Func<CancellationToken, Task> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}
_workItems.Enqueue(workItem);
_signal.Release();
}
public async Task<Func<CancellationToken, Task>> DequeueAsync(
CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);
_workItems.TryDequeue(out var workItem);
return workItem;
}
}
队列托管服务:
public class QueuedHostedService : BackgroundService
{
private readonly ILogger<QueuedHostedService> _logger;
public QueuedHostedService(IBackgroundTaskQueue taskQueue,
ILogger<QueuedHostedService> logger)
{
TaskQueue = taskQueue;
_logger = logger;
}
public IBackgroundTaskQueue TaskQueue { get; }
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(
$"Queued Hosted Service is running.{Environment.NewLine}");
await BackgroundProcessing(stoppingToken);
}
private async Task BackgroundProcessing(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var workItem =
await TaskQueue.DequeueAsync(stoppingToken);
try
{
await workItem(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex,
"Error occurred executing {WorkItem}.", nameof(workItem));
}
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Queued Hosted Service is stopping.");
await base.StopAsync(stoppingToken);
}
}
程序.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<OrdineHelper>();
services.AddHostedService<QueuedHostedService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
这是OrdineHelper.cs
我有几个静态函数的类,其中有ConfirmOrder函数,我必须在其中运行EmailHelper.SendRiepilogoAsync
它返回一个 Task 为QueueBackgroundWorkItem
public class OrdineHelper
{
private static IBackgroundTaskQueue _taskQueue;
public OrdineHelper(IBackgroundTaskQueue taskQueue)
{
_taskQueue = taskQueue;
}
... // LOTS OF STATIC FUNCTIONS
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 = "XXX;";
string query_pagamenti = "XXX";
using var cmd = new MySqlCommand(query_pagamenti, connection);
connection.Open();
...
cmd.ExecuteNonQuery();
if (!tipo.Equals("MENU"))
{
_taskQueue.QueueBackgroundWorkItem(ct => EmailHelper.SendRiepilogoAsync(piva, int.Parse(orderID))); // HERE I MUST RUN QueueBackgroundWorkItem but i get null ref error
}
}
}
ConfirmOrder 在其他静态函数中被调用,如下所示:
public static IActionResult InsertOrdineTakeaway(string piva, string idNegozio, RiepilogoTakeaway ordine, HttpResponse Response)
{
...
if (pagamento.type.Equals("CO"))
{
ConfirmOrder(piva, idOrdine, 0, "", pagamento.id.ToString(), ordine.tipo.ToUpper());
}
Response.Cookies.Append("IDORDER", JsonConvert.SerializeObject(new { idOrdine, piva, payment = pagamento.type }), option);
return new OkObjectResult(new { idOrdine });
}
解决方案
推荐阅读
- angular - 如何在 Angular 11 中滚动查看动态加载的内容?
- java - 为什么这个明显“随机”的数字会打印出“Java is Awesome”
- flutter - 如何让BottomAppBar背景颜色透明
- reactjs - 如何键入带有非可选“children”的 React.FC?
- swift - Swift中的元组赋值`var(x:p,y:q)=(“”,“”)是什么?
- linux - grub 错误 systemd.unified_cgroup_hierarchy=0: 未找到
- javascript - 多个 javascript 承诺 .then 和 .catch 命中错误
- paramiko - paramiko操作网络防火墙遇到一些问题,有什么建议吗?
- flutter - Flutter:如果网络图像不可用,则避免出现异常
- emacs - 在一个文件中使用多种 emacs 模式