hei*_*lch 3 c# asp.net task-queue
我有一个工作服务,它将使用 Cv2 Dnn 执行图像处理。它经过优化以使用所有可用的 CPU,并且运行它的多个实例会降低性能。虽然它运行速度非常快,但如果同时添加两个图像,可能会导致 Dnn 崩溃。
出于这些原因,我希望有一个后台工作人员按顺序从队列中读取数据。所有传入请求都会将其图像添加到此队列并等待结果。
我希望实现的工作流程:
到目前为止,我已经看到了很多将项目推送到队列进行处理的方法,基本上都是“即发即忘”,但没有介绍如何等待项目完成处理。例如,在 Microsoft 关于带有托管服务的后台任务的文档中,他们的排队后台任务示例只是将多个任务推送到队列,然后在添加任务时读取服务,但调用代码不会等待待完成的任务
您可以使用TaskCompetitionSouce来实现此目的。考虑这个具有单个后台线程的简单后台服务:
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;
public class BackgroundService
{
BlockingCollection<ImageQueueItem> _imagesToProcess = new();
public BackgroundService()
{
var thread = new Thread(ProcessImagesThread);
thread.Start();
}
public Task<ImageProcessingResult> ProcessImageQueuedAsync(Image image)
{
var taskCompetitionSource = new TaskCompletionSource<ImageProcessingResult>();
var queueItem = new ImageQueueItem
{
ImageToProcess = image,
ProcessingResult = taskCompetitionSource,
};
_imagesToProcess.Add(queueItem);
return taskCompetitionSource.Task;
}
// background thread that processes images
private void ProcessImagesThread()
{
while(true)
{
var queueItem =_imagesToProcess.Take();
var image = queueItem.ImageToProcess;
var result = new ImageProcessingResult();
try
{
// .............................................................
// process image here and set some properties to result variable
// .............................................................
// complete task by setting result
queueItem.ProcessingResult.SetResult(result);
}
catch(Exception e)
{
// or fail task if processing failed
queueItem.ProcessingResult.SetException(e);
}
}
}
}
// Some data about image to process
public class Image{}
// Some data to return from controller after processing image
public class ImageProcessingResult{}
public class ImageQueueItem
{
public Image ImageToProcess { get; set; }
public TaskCompletionSource<ImageProcessingResult> ProcessingResult { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
该服务可以这样使用:
// awaiting this will wait until Image is processed
var result = await backgroundService.ProcessImageQueuedAsync()
Run Code Online (Sandbox Code Playgroud)