首页 > 其他分享 >webapi动态创建后台任务(使用排队的后台任务)

webapi动态创建后台任务(使用排队的后台任务)

时间:2024-04-29 11:12:33浏览次数:22  
标签:webapi workItem logger stoppingToken await 动态创建 async 后台任务 public

很多时候我们都会使用后台定时任务,但有些任务不需要定时执行,只需要请求到来时执行一次,比如请求服务器到某个地方同步数据,但请求不需要等数据同步完成再响应。这时候就可以使用排队的后台任务。

基本原理是用一个队列保存任务委托,然后用一个后台定时任务依次执行队列中的委托。

MSDN上把源代码都写好了

 1 public interface IBackgroundTaskQueue
 2 {
 3     ValueTask QueueBackgroundWorkItemAsync(Func<CancellationToken, ValueTask> workItem);
 4 
 5     ValueTask<Func<CancellationToken, ValueTask>> DequeueAsync(
 6         CancellationToken cancellationToken);
 7 }
 8 
 9 public class BackgroundTaskQueue : IBackgroundTaskQueue
10 {
11     private readonly Channel<Func<CancellationToken, ValueTask>> _queue;
12 
13     public BackgroundTaskQueue(int capacity)
14     {
15         // Capacity should be set based on the expected application load and
16         // number of concurrent threads accessing the queue.            
17         // BoundedChannelFullMode.Wait will cause calls to WriteAsync() to return a task,
18         // which completes only when space became available. This leads to backpressure,
19         // in case too many publishers/calls start accumulating.
20         var options = new BoundedChannelOptions(capacity)
21         {
22             FullMode = BoundedChannelFullMode.Wait
23         };
24         _queue = Channel.CreateBounded<Func<CancellationToken, ValueTask>>(options);
25     }
26 
27     public async ValueTask QueueBackgroundWorkItemAsync(
28         Func<CancellationToken, ValueTask> workItem)
29     {
30         if (workItem == null)
31         {
32             throw new ArgumentNullException(nameof(workItem));
33         }
34 
35         await _queue.Writer.WriteAsync(workItem);
36     }
37 
38     public async ValueTask<Func<CancellationToken, ValueTask>> DequeueAsync(
39         CancellationToken cancellationToken)
40     {
41         var workItem = await _queue.Reader.ReadAsync(cancellationToken);
42 
43         return workItem;
44     }
45 }
BackgroundTaskQueue
 1 public class QueuedHostedService : BackgroundService
 2 {
 3     private readonly ILogger<QueuedHostedService> _logger;
 4 
 5     public QueuedHostedService(IBackgroundTaskQueue taskQueue, 
 6         ILogger<QueuedHostedService> logger)
 7     {
 8         TaskQueue = taskQueue;
 9         _logger = logger;
10     }
11 
12     public IBackgroundTaskQueue TaskQueue { get; }
13 
14     protected override async Task ExecuteAsync(CancellationToken stoppingToken)
15     {
16         _logger.LogInformation(
17             $"Queued Hosted Service is running.{Environment.NewLine}" +
18             $"{Environment.NewLine}Tap W to add a work item to the " +
19             $"background queue.{Environment.NewLine}");
20 
21         await BackgroundProcessing(stoppingToken);
22     }
23 
24     private async Task BackgroundProcessing(CancellationToken stoppingToken)
25     {
26         while (!stoppingToken.IsCancellationRequested)
27         {
28             var workItem = 
29                 await TaskQueue.DequeueAsync(stoppingToken);
30 
31             try
32             {
33                 await workItem(stoppingToken);
34             }
35             catch (Exception ex)
36             {
37                 _logger.LogError(ex, 
38                     "Error occurred executing {WorkItem}.", nameof(workItem));
39             }
40         }
41     }
42 
43     public override async Task StopAsync(CancellationToken stoppingToken)
44     {
45         _logger.LogInformation("Queued Hosted Service is stopping.");
46 
47         await base.StopAsync(stoppingToken);
48     }
49 }
QueuedHostedService
services.AddHostedService<QueuedHostedService>();
services.AddSingleton<IBackgroundTaskQueue>(ctx =>
{
    int queueCapacity = 100;
    return new BackgroundTaskQueue(queueCapacity);
});

然后在控制器的方法中向队列中添加委托即可

await _backgroundTaskQueue.QueueBackgroundWorkItemAsync(async token =>
{
    await SyncPersonPhotoAsync(persons);
});

 

标签:webapi,workItem,logger,stoppingToken,await,动态创建,async,后台任务,public
From: https://www.cnblogs.com/ggtc/p/18165246

相关文章

  • WEBAPI传参及默认首页设置
    开发工具:VS2017创建WEBAPI,1.选择ASP.NETCoreWeb应用程序2.选择如下,HTTPS配置勾选去掉,暂不配置3.“属性”中调试默认界面及launchsettings.json 4.调试以后默认页面 5. ......
  • .Net WebAPI程序集成CAS单点登录-API方式(不使用DotNetCasClient)
    以下是ashx一般处理程序的示例,且cas登录单独放到了一个按钮中:1、登录按钮(js)- console.log("cos登录");varoriginStr=window.location.origin;window.location.href="https://cas.your.com/cas/login?service="+originStr+"/WebUI/Admin......
  • IIS 部署WEBAPI
    ASP.NETCore不再是由IIS工作进程(w3wp.exe)托管,而是使用自托管Web服务器(Kestrel)运行,IIS则是作为反向代理的角色转发请求到Kestrel不同端口的ASP.NETCore程序中,随后就将接收到的请求推送至中间件管道中去,处理完你的请求和相关业务逻辑之后再将HTTP响应数据重新回写到IIS中,最终转达......
  • webapi路由
    ShopController.cspublicclassShopController:ApiControllerBase{[Route("api/v1/shop/watermark")][HttpPost]publicApiResultwatermark(dynamicvalue){//watermark/shopname.txtA......
  • 一文读懂.NET WebAPI中FromRoute、FromQuery、FromBody的关键角色与用法
    .NETWebAPI作为一种构建RESTful服务的强大工具,为开发者提供了便捷的方式来定义、处理HTTP请求并返回响应。在设计API接口时,正确地接收和解析客户端发送的数据至关重要。.NETWebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用于指示控制器方法应如何从不同的请求......
  • ABP -Vnext框架一步一步入门落地教程——使用ABP -Vnext创建一个WEBAPI接口(二)
    人生需要指引,而复制是成功最快的方式,兄弟们让我们发车吧————代码大牛ljy开发主题:何谓开发应用服务端在官方开发教程这一段的内容叫做开发应用服务端,作为现在前后端分离的开发模式来说,一个应用就分为前端页面框架和后端API,页面框架调用WEBAPI实现业务就完事了。所以咱们今天......
  • Asp.Net Core WebApi使用Swagger分组展示接口
    先通过Nuget包管理器安装Swashbuckle.AspNetCore包,然后修改Startup.cs的ConfigureServices方法:services.AddSwaggerGen(c=>{//添加swagger文档c.SwaggerDoc("system",newOpenApiInfo(){......
  • c# Framwork4.5 添加webapi处理跨域请求问题
     常用2种方式 1)web.config允许所有来源,HTTP方法,请求标头跨域:后端,在Web.config中找到<system.webServer>标签,里面添加配置如下:<httpProtocol><customHeaders><addname="Access-Control-Allow-Origin"value="*"/><addname="Acc......
  • ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
    ASP.NETMVCWebApi接口返回JOSN日期格式化dateformat全局配置WebApiConfigpublicstaticclassWebApiConfig{publicstaticvoidRegister(HttpConfigurationconfig){//WebAPI配置和服务//WebAPI路由config.MapHttpAttributeRoutes......
  • JS——webAPIs(6)
    一、知识点1.正则表达式的使用//正则表达式:用于匹配字符串中字符组合的模式conststr='学习前端'//定义规则constreg=/前端///进行查找-两个方法//用于判断是否有符合规则的字符串,返回布尔值console.log(reg.test(str));//用于......