using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Lskj.Util { public class TaskSchedulerUtil : TaskScheduler { /// /// WinForms 会在后台线程第一次构造控件时自动安装 /// WindowsFormsSynchronizationContext。预加载任务只能执行数据准备, /// 不应把线程池线程注册成 WinForms UI 线程;否则 DevExpress manager /// 会绑定到已经没有消息循环的线程,导致模块打开/关闭后的残留和卡死。 /// 这里只在线程池任务执行期间使用一个非 WinForms 的同步上下文 /// 作为占位,不改变调度器的并发度,也不触碰真正的 UI 线程上下文。 /// 不能直接使用 SynchronizationContext 基类实例:WinForms 的 /// InstallIfNeeded 会把“基类实例”视为未安装状态并再次替换为 /// WindowsFormsSynchronizationContext;必须使用独立派生类型。 /// private void ExecuteTaskWithoutWinFormsContext(Task task) { SynchronizationContext previousContext = SynchronizationContext.Current; bool replaceContext = previousContext == null || previousContext is WindowsFormsSynchronizationContext; if (replaceContext) { SynchronizationContext.SetSynchronizationContext( new BackgroundSynchronizationContext()); } try { TryExecuteTask(task); } finally { if (replaceContext) { SynchronizationContext.SetSynchronizationContext( previousContext); } } } /// /// 标记后台线程已明确配置同步上下文,阻止 WinForms 按“空/基类上下文” /// 自动安装 WindowsFormsSynchronizationContext。继承基类的默认 Post /// 实现仍将延续任务投递到线程池,不改变普通后台任务语义。 /// private sealed class BackgroundSynchronizationContext : SynchronizationContext { public override SynchronizationContext CreateCopy() { return new BackgroundSynchronizationContext(); } } private readonly LinkedList _tasks = new LinkedList(); //任务队列 private readonly int _maxDegreeOfParallelism; //最大并发线程数 private int _runningTasks = 0; //当前正在运行的线程数 private readonly object _lock = new object(); //用于线程同步 public TaskSchedulerUtil(int maxDegreeOfParallelism) { if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException(nameof(maxDegreeOfParallelism)); _maxDegreeOfParallelism = maxDegreeOfParallelism; } // 将任务加入队列 protected override void QueueTask(Task task) { lock (_lock) { _tasks.AddLast(task); // 将任务加入队列 TryExecuteNextTask(); // 尝试执行下一任务 } } // 尝试执行下一个任务 private void TryExecuteNextTask() { lock (_lock) { // 如果当前运行的线程数小于最大并发数,且队列中还有任务 while (_runningTasks < _maxDegreeOfParallelism && _tasks.Count > 0) { var task = _tasks.First.Value; _tasks.RemoveFirst(); // 取出一个任务 _runningTasks++; // 增加正在运行的任务计数 // 在线程池中运行任务 ThreadPool.QueueUserWorkItem(_ => { try { ExecuteTaskWithoutWinFormsContext(task); } finally { lock (_lock) { _runningTasks--; // 减少正在运行的任务计数 TryExecuteNextTask(); // 尝试执行下一个任务 } } }); } } } // 尝试在线程中直接运行任务(不支持) protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { // 不允许直接在线程中运行任务(可以根据需求修改) return false; } // 返回已计划的任务(用于调试) protected override IEnumerable GetScheduledTasks() { lock (_lock) { return _tasks.ToList(); } } } }