在我们业务操作时,难免会有多次操作,我们期望什么结果呢? 绝大部分情况,应该是只需要最后一次操作的结果,其它操作应该无效。 自定义等待的任务类 1. 可等待的任务类 AwaitableTask: View Code 无效的操作可以分为以下俩种: 已经进行中的操作,后续结果应标记为无效 还没开始的操作,后续不执行 自定义任务类型 AwaitableTask中,添加俩个字段NotExecutable、IsInvalid: 复制代码 1 /// 2 /// 获取任务是否为不可执行状态 3 /// 4 public bool NotExecutable { get; private set; } 5 /// 6 /// 获取任务是否有效 7 /// 注:对无效任务,可以不做处理。减少并发操作导致的干扰 8 /// 9 public bool IsInvalid { get; private set; } = true; 复制代码 2. 有返回结果的可等待任务类 AwaitableTask: View Code 添加任务等待器,同步等待结果返回: 复制代码 1 /// 2 /// 获取任务等待器 3 /// 4 /// 5 public new TaskAwaiter GetAwaiter() => new TaskAwaiter(this); 6 7 /// 8 /// 任务等待器 9 /// 10 [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)] 11 public new struct TaskAwaiter : INotifyCompletion 12 { 13 private readonly AwaitableTask _task; 14 15 /// 16 /// 初始化任务等待器 17 /// 18 /// 19 public TaskAwaiter(AwaitableTask awaitableTask) => _task = awaitableTask; 20 21 /// 22 /// 任务是否已完成。 23 /// 24 public bool IsCompleted => _task._task.IsCompleted; 25 26 /// 27 public void OnCompleted(Action continuation) 28 { 29 var This = this; 30 _task._task.ContinueWith(t => 31 { 32 if (!This._task.NotExecutable) continuation?.Invoke(); 33 }); 34 } 35 36 /// 37 /// 获取任务结果。 38 /// 39 /// 40 public TResult GetResult() => _task._task.Result; 41 } 复制代码 异步任务队列 添加异步任务队列类,用于任务的管理,如添加、执行、筛选等: View Code 1. 自动取消之前的任务 AutoCancelPreviousTask 内部使用线程,循环获取当前任务列表,如果当前任务被标记NotExecutable不可执行,则跳过。 NotExecutable是何时标记的? 获取任务时,标记所有获取的任务为NotExecutable。直到任务列表中为空,那么只执行最后获取的一个任务。 2. 标记已经进行的任务无效 MarkTaskValid 当前进行的任务,无法中止,那么标记为无效即可。 复制代码 1 /// 2 /// 上一次异步操作 3 /// 4 private AwaitableTask _lastDoingTask; 5 private bool TryGetNextTask(out AwaitableTask task) 6 { 7 task = null; 8 while (_queue.Count > 0) 9 { 10 //获取并从队列中移除任务 11 if (_queue.TryDequeue(out task) && (!AutoCancelPreviousTask || _queue.Count == 0)) 12 { 13 //设置进行中的异步操作无效 14 _lastDoingTask?.MarkTaskValid(); 15 _lastDoingTask = task; 16 return true; 17 } 18 //并发操作,设置任务不可执行 19 task.SetNotExecutable(); 20 } 21 return false; 22 } 复制代码 后续执行完后,根据此标记,设置操作结果为空。 复制代码 1 /// 2 /// 执行异步操作 3 /// 4 /// 返回结果类型 5 /// 异步操作 6 /// isInvalid:异步操作是否有效;result:异步操作结果 7 public async Task<(bool isInvalid, T reslut)> ExecuteAsync(Func> func) 8 { 9 var task = GetExecutableTask(func); 10 var result = await await task; 11 if (!task.IsInvalid) 12 { 13 result = default(T); 14 } 15 return (task.IsInvalid, result); 16 } 复制代码 实践测试 启动10个并发任务,测试实际的任务队列并发操作管理: 复制代码 1 public MainWindow() 2 { 3 InitializeComponent(); 4 _asyncTaskQueue = new AsyncTaskQueue 5 { 6 AutoCancelPreviousTask = true, 7 UseSingleThread = true 8 }; 9 } 10 private AsyncTaskQueue _asyncTaskQueue; 11 private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 12 { 13 // 快速启动10个任务 14 for (var i = 1; i < 10; i++) 15 { 16 Test(_asyncTaskQueue, i); 17 } 18 } 19 public static async void Test(AsyncTaskQueue taskQueue, int num) 20 { 21 var result = await taskQueue.ExecuteAsync(async () => 22 { 23 Debug.WriteLine("输入:" + num); 24 // 长时间耗时任务 25 await Task.Delay(TimeSpan.FromSeconds(5)); 26 return num * 100; 27 }); 28 Debug.WriteLine($"{num}输出的:" + result); 29 } 复制代码 测试结果如下: 只有最后一次操作结果,才是有效的。其它9次操作,一次是无效的,8次操作被取消不执行。https://www.cnblogs.com/kybs0/p/11988554.html