C# dotnet 高性能多线程工具 ExecuteOnceAwaiter 只执行一次的任务
本文将安利大家一个好用的工具,用来解决这样的问题,我有一个任务,要求这个任务在执行过程中不能被重入,只有在任务执行完成之后才能重置状态重新执行一次。换句话说就是在此任务正在执行过程中,不能重复进入此任务。同时在任务执行过程中,不能重置任务状态。在任务执行完成之后,可以保存任务的状态,直接返回任务结果。在任务执行完成之后,可以调用重置状态方法,让任务可以再次重新调用
本文的这个 ExecuteOnceAwaiter 是放在 dotnetCampus.AsyncWorkerCollection 库的工具,此项目在 github 开源,开源地址请看 https://github.com/dotnet-campus/AsyncWorkerCollection
适用
支持本机内多线程调用某一确定的任务的执行,任务仅执行一次,多次调用均返回相同结果
在任务执行完成之后,可以重置任务状态,让任务再次执行
如用来作为执行 同步 这个业务的工具。也就是在 同步 这个业务执行过程中,不允许再次执行 同步 这个业务。同时只要同步过了,那么再次调用只是返回同步结果。只有在同步之后状态发生变更之后,才能再次同步
使用方法
通过 NuGet 安装 dotnetCampus.AsyncWorkerCollection 库
使用 ExecuteOnceAwaiter 需要创建传入执行的任务,传入任务支持给定任务返回值的泛形
public ExecuteOnceAwaiter<FooInfo> ExecuteOnceAwaiter { get; set; }
var executeOnceAwaiter = new ExecuteOnceAwaiter<FooInfo>(AsyncAction);
ExecuteOnceAwaiter = executeOnceAwaiter;
上面代码的 AsyncAction 可以是委托或本地方法,要求此方法返回值是 Task<FooInfo>
而此返回值 FooInfo
是自定义的类型,用于替换 ExecuteOnceAwaiter 的泛形
private async Task<FooInfo> AsyncAction()
{
// 忽略代码
}
调用 ExecuteOnceAwaiter 的方法只有两个,一个是 ExecuteAsync 另一个是 ResetWhileCompleted 方法
调用 ExecuteAsync 的方法可以执行任务,如果任务的状态是没有执行,那么任务将执行。如果任务正在执行,或执行完成,那么将不会再次执行任务,而是返回 Task 用于等待获取任务执行结果
调用 ResetWhileCompleted 方法可以用来重置任务的状态,可以让任务支持再次被调用。重置任务状态仅在任务没有执行或任务执行完成之后才能生效。如果此时任务正在执行,那么调用 ResetWhileCompleted 方法 将什么都不做
例子
本文使用一个简单的 WPF 作为例子,这个界面很简单,就两个按钮,一个是启动任务,另一个是重置任务
执行的效果如下图,在点击启动任务多次的时候,只有一个任务在执行。在任务执行过程点击重置任务是啥都不做。在任务执行完成之后,点击重置任务,可以重新运行任务
界面代码如下
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid>
<TextBlock x:Name="LogTextBlock" Margin="10,10,10,10" TextWrapping="Wrap" VerticalAlignment="Bottom"></TextBlock>
</Grid>
<StackPanel Grid.Row="1" Margin="10,10,10,10"
Orientation="Horizontal" >
<Button Margin="10,10,10,10" Content="启动任务" Click="StartTaskButton_OnClick"></Button>
<Button Margin="10,10,10,10" Content="重置任务" Click="ResetTaskButton_OnClick"></Button>
</StackPanel>
</Grid>
后台代码如下
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ExecuteOnceAwaiter<FooInfo> ExecuteOnceAwaiter { get; set; }
public MainWindow()
{
InitializeComponent();
var executeOnceAwaiter = new ExecuteOnceAwaiter<FooInfo>(AsyncAction);
ExecuteOnceAwaiter = executeOnceAwaiter;
}
private async Task<FooInfo> AsyncAction()
{
for (int i = 0; i < 10; i++)
{
await Dispatcher.InvokeAsync(() =>
{
LogTextBlock.Text += $"执行任务 {i+1}/10rn";
});
await Task.Delay(TimeSpan.FromMilliseconds(500));
}
return new FooInfo();
}
private void StartTaskButton_OnClick(object sender, RoutedEventArgs e)
{
LogTextBlock.Text += $"点击启动任务按钮rn";
ExecuteOnceAwaiter.ExecuteAsync();
}
private void ResetTaskButton_OnClick(object sender, RoutedEventArgs e)
{
LogTextBlock.Text += $"点击重置任务按钮rn";
ExecuteOnceAwaiter.ResetWhileCompleted();
}
}
public class FooInfo
{
}
代码放在github欢迎小伙伴访问
感谢
此库 dotnet-campus/AsyncWorkerCollection: 多线程异步工具 由多线程砖家头像 用了一年的时间写的。在我所在团队的各大项目使用,经过两年时间大概 200 万台设备的测试是稳的。但是多线程很复杂,因为自己业务使用也许没有测试出坑,于是开源出来,请小伙伴协助测试
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。
- Linux系统下yum镜像源环境部署记录
- 特斯拉vs凯迪拉克vs奔驰:三大汽车自动驾驶系统比拼
- Centos下添加静态路由(临时和永久有效)的操作记录
- python如何保证输入键入数字
- 微信小程序自定义数据分析试水
- 挂载银行前置机Ukey到windows server2012虚拟机的操作记录
- 文件上传速度查询方法
- “AS3.0高级动画编程”学习:第三章等角投影(上)
- su: 无法设置用户ID: 资源暂时不可用
- NumPY学习笔记
- LVS负载均衡下session共享的实现方式-持久化连接
- Centos6.9下RabbitMQ集群部署记录
- “AS3.0高级动画编程”学习:第三章等角投影(下)
- zabbix监控主机cpu达到80%后报警
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法