webapi动态创建后台任务(使用排队的后台任务)
很多时候我们都会使用后台定时任务,但有些任务不需要定时执行,只需要请求到来时执行一次,比如请求服务器到某个地方同步数据,但请求不需要等数据同步完成再响应。这时候就可以使用排队的后台任务。
基本原理是用一个队列保存任务委托,然后用一个后台定时任务依次执行队列中的委托。
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动态创建后台任务(使用排队的后台任务)的更多相关文章
- 动态创建Lambda表达式实现高级查询
需求简介 最近这几天做的东西总算是回归咱的老本行了,给投资管理项目做一个台账的东西,就是类似我们的报表.其 中有一个功能是一个高级查询的需求,在查询条件方面大概有7.8个查询条件.需求就是如果一个条件 ...
- k8s-jenkins x CI/CD 动态创建slave---01
jenkins CI/CD(动态创建slave)简述: 由于之前管理kubernetes集群应用发布,用的是Gitlab-CI,用作开发环境管理还可以,生产环境管理发布,缺点太多,打包速度很慢.研究新 ...
- JavaScript dom 动态创建标记
此前的大多数DOM都是用来查找元素,getElementById和getElementsByTagName都可以方便快捷的找到文档中的某个或者某些特定的元素节点,这些元素随后可以用诸如setAttri ...
- ios动态创建类Class
[Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...
- winform 用户控件、 动态创建添加控件、timer控件、控件联动
用户控件: 相当于自定义的一个panel 里面可以放各种其他控件,并可以在后台一下调用整个此自定义控件. 使用方法:在项目上右键.添加.用户控件,之后用户控件的编辑与普通容器控件类似.如果要在后台往窗 ...
- python动态创建类的声明
动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类 ...
- Python 动态创建函数【转】
知乎上也有相似的问题 偶然碰到一个问题,初想是通过动态创建Python函数的方式来解决,于是调研了动态创建Python函数的方法. 定义lambda函数 在Python中定义lambda函数的写法很简 ...
- WinForm用户控件、动态创建添加控件、timer控件--2016年12月12日
好文要顶 关注我 收藏该文 徐淳 关注 - 1 粉丝 - 3 0 0 用户控件: 通过布局将多个控件整合为一个控件,根据自己的需要进行修改,可对用户控件内的所有控件及控件属性进行修 ...
- 动态创建DAL层类的实例
为了可扩展性,方便以后对于代码的修改维护,使用动态创建DAL层对象. 1.首先在webconfig中的configuration下添加配置项 <appSettings> <add k ...
- [转]android:动态创建多个按钮 及 批量设置监听
之前投机取巧,先创建好多个按钮,再根据需要的数量进行部分隐藏,不过还是逃不过呀. 这样根本无法批量地 findId,批量地 设置监听. 所以今天还是认认真真地研究回“动态创建按钮”,终于,通过不断尝试 ...
随机推荐
- OpenHarmony父子组件单项同步使用:@Prop装饰器
@Prop装饰的变量可以和父组件建立单向的同步关系.@Prop装饰的变量是可变的,但是变化不会同步回其父组件. 说明: 从API version 9开始,该装饰器支持在ArkTS卡片中使用. 概述 ...
- C# PropertyChanged 事件-数据绑定
在.NET平台上,数据绑定是一项令人十分愉快的技术.利用数据绑定能减少代码,简化控制逻辑. 通常,可以将某个对象的一个属性绑定到一个可视化的控件上,当属性值改变时,控件上的显示数据也随之发生变化.要实 ...
- Linux:vscode扩展无法下载,报错:Error while fetching extensions : XHR failed
在Linux系统上下载安装好vscode以后,发现扩展里面无法下载安装,报错:Error while fetching extensions : XHR failed 解决办法:修改 hosts 文件 ...
- Ubuntu部署Django一:环境搭建
前言: Ubuntu系统上部署django,使用的部署方案是 Ubuntu + django + uwsgi + nginx Ubuntu系统版本用的是 ubuntu-20.04.2.0-desk ...
- 国密 SM2 的非对称签名验签过程
国密 SM2 的非对称签名验签过程 介绍 非对称加密确保了消息传输中的保密性,但是由于使用公钥加密,而公钥是分发出去的,可能泄露,谁都可以使用公钥加密发送消息. 因此为了保证收到的消息是由对应的发送者 ...
- ionic 4 app 自动版本更新
前言 介绍一下ionic4 app的自动更新.ionic 不多介绍了,后面一个后系列,背负着骂名的ionic其实还是可以的,如果刚入门ionic可能觉得很坑,但是呢,往后你就发现另外一件事,那就是其他 ...
- https http2 http3
HTTP 1.1 对比 1.0,HTTP 1.1 主要区别主要体现在: 缓存处理:在 HTTP 1.0 中主要使用 header 里的 If-Modified-Since,Expires 来做为缓存判 ...
- 推荐一波微软家的浏览器:EDGE
前段时间英雄联盟(LOL)队伍 EDG 夺冠成为热门事件,上了各大热搜,即使大家不玩英雄联盟,相信也多多少少有听说相关信息吧! 今天我们的主角并不是 EDG,而是微软的新版浏览器 EDGE !!! 微 ...
- 对于小程序canvas在某些情况下touchmove 不能触发导致的签名不连续替代方案(企微)
1.问题 微信开放社区链接 尝试过新版canvas,在企业微信中签名依然是依然断触,有问题的手机是iphoe15,系统版本以及企微版本微信版本均与签名正常的手机一致,但是那个手机就是无法正常签字,在微 ...
- 使用ollama分别在我的window、mac、小米手机上部署体验llama3-8b
1.ollama到底是个什么玩意 一句话来说, Ollama 是一个基于 Go 语言开发的简单易用的本地大模型运行框架.可以将其类比为 docker(有类似docker中的一些常规命令list,pul ...