/// <summary> /// 以KeepLast策略执行重入任务。此方法确保线程安全。 /// </summary> private async void Run() { var isRunning = Interlocked.CompareExchange(ref _isRunning, 1, 0); if (isRunning is 1) { lock (_locker) { if (_isRunning is 1) { // 当前已经在执行队列,因此无需继续执行。 return; } } } //下面这段是在临界区执行的,不存在多线程问题 var hasTask = true; while (hasTask) { TaskWrapper runTask = null; // 当前还没有任何队列开始执行,因此需要开始执行队列。 while (_queue.TryDequeue(out var wrapper)) { //所有任务项转入执行队列 if (runTask != null) { _skipQueue.Enqueue(runTask); } runTask = wrapper; } if (runTask != null) { // 内部已包含异常处理,因此外面可以无需捕获或者清理。 await runTask.RunAsync().ConfigureAwait(false); //完成后对等待队列中的项赋值 if (runTask.Exception != null) { SetException(runTask.Exception); } else { SetResult(runTask.Result); } } lock (_locker) { hasTask = _queue.TryPeek(out _); if (!hasTask) { //退出临界区 _isRunning = 0; } } } }