Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在托管服务中添加多个队列_C#_Asp.net Core_.net Core_Queue_Backgroundworker - Fatal编程技术网

C# 在托管服务中添加多个队列

C# 在托管服务中添加多个队列,c#,asp.net-core,.net-core,queue,backgroundworker,C#,Asp.net Core,.net Core,Queue,Backgroundworker,我正在使用示例实现队列 这就是我的代码的外观: 在startup.cs中,我正在添加托管服务和后台队列 services.AddHostedService(); services.AddSingleton() 然后,我实现作用域服务、托管服务和后台队列,如下所示: namespace Services.Services{ 公共类QueuedHostedService:BackgroundService{ 专用只读ILogger\u记录器; 私有只读服务器ViceProvider\u服务提供商;

我正在使用示例实现队列

这就是我的代码的外观:

在startup.cs中,我正在添加托管服务和后台队列

services.AddHostedService();
services.AddSingleton()

然后,我实现作用域服务、托管服务和后台队列,如下所示:

namespace Services.Services{
公共类QueuedHostedService:BackgroundService{
专用只读ILogger\u记录器;
私有只读服务器ViceProvider\u服务提供商;
public QueuedHostedService(IServiceProvider服务提供程序、IBackgroundTaskQueue任务队列、ILoggerFactory loggerFactory){
_服务提供者=服务提供者;
TaskQueue=TaskQueue;
_logger=loggerFactory.CreateLogger();
}
公共IBackgroundTaskQueue任务队列{
得到;
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken CancellationToken){
而(!cancellationToken.IsCancellationRequested){
var workItem=await TaskQueue.DequeueAsync(cancellationToken);
试一试{
等待工作项(取消令牌);
}捕获(例外情况除外){
}
}
}
}
}
公共接口IBackgroundTaskQueue{
作废QueueBackgroundWorkItem(FuncworkItem);
Task>DequeueAsync(CancellationToken CancellationToken);
}
命名空间服务{
公共类BackgroundTaskQueue:IBackgroundTaskQueue{
私有ConcurrentQueue>_workItems=新ConcurrentQueue>();
私有信号量lim _signal=新信号量lim(0);
public void QueueBackgroundWorkItem(FuncworkItem){
if(workItem==null){
抛出新ArgumentNullException(nameof(workItem));
}
_workItems.Enqueue(workItem);
_信号。释放();
}
公共异步任务>出列异步(CancellationToken CancellationToken){
wait_signal.WaitAsync(cancellationToken);
_workItems.TryDequeue(输出
变量(工作项);
返回工作项;
}
}
}
//作用域服务
命名空间服务{
公共类导入服务:BaseService、IImportService{
私有只读IFileProcessingService\u作用域处理服务;
专用只读配置设置\u配置设置;
公共IBackgroundTaskQueue队列{
得到;
}
私有的
常量字符串AZURE\u BLOB\u CONTAINER=“blobcontainer”;
公共服务供应商{
得到;
}
公共导入服务(IServiceProvider服务,IBackgroundTaskQueue队列):基本(服务){
服务=服务;
_configurationSettings=services.GetService();
_scopedProcessingService=services.GetProcessingService();
队列=队列;
}
//----主文件
公共异步任务导入文件(字符串文件路径、长文件大小、int userId、FileFormatType文件格式、TransactionDataHeaderMap DataHeaderMap、字符串分隔符、字符串日期格式){
wait _scopedProcessingService.ImportFile(文件路径、文件大小、用户ID、文件格式、数据头映射、分隔符、日期格式);
}
公共异步任务UploadToBlobStorage(IFormFile文件、int userId、TransactionalDataFileType){
var fileFormat=GetFileFormat(文件);
var tempFilePath=await GetTemporaryPath(文件);
var fileName=userId.ToString()+“-”+DateTime.Now+“+fileFormat;
// ....... //
ProcessFile(临时文件路径、文件格式、文件、类型、用户ID);
}
私有void ProcessFile(字符串tempFilePath、FileFormatType fileFormat、IFormFile文件、Tyoe类型、int userId){
var分隔符=“,”;
Queue.QueueBackgroundWorkItem(异步令牌=>{
使用(var scope=Services.CreateScope()){
var scopedProcessingService=
scope.ServiceProvider
.GetRequiredService();
//处理
开关(类型){
案例“csv”:
等待scopedProcessingService.ImportFile(tempFilePath、file.Length、userId、fileFormat、new Headers()、分隔符??“,”,“yyyy-MM-dd”);
打破
}
}
});
}
}
}
  • 第一个选项是最简单的-您只需创建一组类和接口
    QueuedHostedServiceA
    QueuedHostedServiceB
    IBackgroundTaskQueueA
    。。(您可以使用继承来减少代码重复)

  • 此外,您还可以引入“处理程序”的概念,并使所有这些内容通用:


  • 当需要时,将消息放入队列。

    是的,添加另一对服务是实现这一点的方法之一。这是最好的方法吗?还有什么办法?这取决于具体情况。另一个是处理引入消息类型的概念,并在一个队列中处理不同的消息。因此,我可以拥有一个
    QueuedHostedService
    ,只需使用
    queue.QueueBackgroundWorkItem(异步令牌…
    类似于
    ProcessFile()中的
    方法?或者更好的做法是使用例如
    FileProcessingHostedService
    和另一个
    CalculationHostedService
    ?类似于这里的方法?但是我是否需要为每个方法使用
    BackgroundTaskQueue
    ?也许你知道我可以查找的其他示例资源?提前谢谢你是的,这是个想法。你知道吗可以尝试重用BackgroundTaskQueue添加泛型。如果您愿意,我可以稍后对此进行详细说明。非常感谢您的回答!再问一个问题。
    class ProcessFile(string tempFilePath,FileFormatType fileFormat,IFormFile file,Type Type,int userId){}
    ?它应该只包含具有处理所需参数的构造函数?很抱歉问了这么多,我真的很想理解。我还可以调用不同的服务
    interface IHandler<T> { Task Handle(T msg, CancelationToken ...)}
    interface IBackgroundMessageQueue<T> {...} // same impl but with T instead of Func<CancellationToken,Task>
    class IBackgroundMessageQueue<T> {...} // same impl but with T instead of Func<CancellationToken,Task>
    
    class QueuedHostedService<T>
    {
       public QueuedHostedService(..., IBackgroundMessageQueue<T> queue, IHandler<T> h) {... }
       protected override async Task ExecuteAsync(CancellationToken cancellationToken) {
          while (!cancellationToken.IsCancellationRequested) {
            T message = await queue.DequeueAsync(cancellationToken);
    
            try {
                using(var scp = serviceProvider.CreateScope())
                {
                    var handler = ServiceProvider.GetRequiredService<IHandler<T>>;
                  await handler.Handle(message, cancellationToken);
                }
            } catch (Exception ex) {
    
            }
          }
        }
    }
    
    class ProcessFile(string tempFilePath, FileFormatType fileFormat, IFormFile file, Tyoe type, int userId){}
    
    FileProcessor: IHandler<ProcessFile> {implement your logic from ImportService.ProcessFile}
    
    services.AddScoped<IHandler<ProcessFile>, FileProcessor>()
    services.AddSingleton<IBackgroundTaskQueue<ProcessFile>, BackgroundTaskQueue<ProcessFile>>();
    
    services.AddHostedService<QueuedHostedService<ProcessFile>>();
    
    public ImportService(IBackgroundMessageQueue<ProcessFile> queue)