コード例 #1
0
        /// <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;
                    }
                }
            }
        }