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,批量地 设置监听. 所以今天还是认认真真地研究回“动态创建按钮”,终于,通过不断尝试 ...
随机推荐
- Spring 框架模块深度解析:核心容器、数据访问、Web 层与其他关键模块
Spring 可能成为您的所有企业应用程序的一站式商店.但是,Spring 是模块化的,允许您挑选适用于您的模块,而无需引入其他模块.下面的部分提供了 Spring Framework 中所有可用模块 ...
- HarmonyOS极客松“上分秘籍”! 高手们顶峰相见!
HarmonyOS 极客马拉松2023 火热进行中,我们期待与各位开发者相聚一起,践行极客精神,创造无限可能! 我们鼓励各位极客们自由组队,挥洒创意,用HarmonyOS 探索移动应用和服务的更多 ...
- k8s之存储卷OpenEBS
一.OpenEBS简介 OpenEBS 是一种开源云原生存储解决方案,托管于 CNCF 基金会,目前该项目处于沙箱阶段. OpenEBS能够将Kubernetes工作节点上可用的住何存储转换为术卷或分 ...
- react native 如何用vs code 进行调试
前言 以前做react-native 写的文章,在此分享一下. 在react-native 中有两种方式调试,一种是crome 调试,一种是本地调试,接下来介绍的是本地调试. 解决方案 在vs cod ...
- -source 1.5 中不支持 diamond 运算符(中文版idea)
-source 1.5 中不支持 diamond 运算符(中文版idea) 将idea中的各个部分的jdk设为8即可,中文版的如下 1.文件-设置 2.项目上右击-打开模块设置 模块中每一个都要确认是 ...
- 力扣1127(MySQL)-用户购买平台(困难)
题目: 支出表: Spending 这张表记录了用户在一个在线购物网站的支出历史,该在线购物平台同时拥有桌面端('desktop')和手机端('mobile')的应用程序.这张表的主键是 (user_ ...
- 力扣578(MySQL)-查询回答率最高的问题(中等)
题目: 从 survey_log 表中获得回答率最高的问题,survey_log 表包含这些列:id, action, question_id, answer_id, q_num, timestamp ...
- 力扣128(java&python)-最长连续序列(中等)
题目: 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度. 请你设计并实现时间复杂度为 O(n) 的算法解决此问题. 示例 1: 输入:nums = ...
- API 开发的后盾:平台工程提供强力动态支持
过去几年,开发团队一直在发展传统的 DevOps.一些开发人员认为,CloudOps 或 DeploymentOps 等新实践的兴起将会导致回到孤岛问题.其他人则不愿意在承担所有其他职责之外构建.部署 ...
- 2022飞天技术峰会:硬之城如何基于 SAE 打造数智化电子工业互联网平台
简介: 全球数字化时代已经到来,数字经济正推动生产方式.生活方式和治理方式的深刻变化,成为重组全球要素资源,重塑经济结构,改变全球竞争格局的关键力量. 本文根据硬之城 CEO 李六七先生在峰会上的分享 ...