using System; using System.Threading; namespace Lskj.Control { /// /// 串行处理请求,并在繁忙时只保留最后一次请求。 /// 用于输入联想控件,避免每次 TextChanged 都创建独立线程。 /// internal sealed class LatestValueWorker : IDisposable { private readonly object _syncRoot = new object(); private readonly Action _work; private T _pendingValue; private bool _hasPendingValue; private bool _workerRunning; private bool _disposed; private int _version; public LatestValueWorker(Action work) { if (work == null) { throw new ArgumentNullException("work"); } _work = work; } public int Queue(T value) { bool startWorker = false; int version; lock (_syncRoot) { if (_disposed) { return -1; } version = ++_version; _pendingValue = value; _hasPendingValue = true; if (!_workerRunning) { _workerRunning = true; startWorker = true; } } if (startWorker && !ThreadPool.QueueUserWorkItem(Run)) { lock (_syncRoot) { _workerRunning = false; } throw new InvalidOperationException("无法启动输入联想查询任务。"); } return version; } public bool IsCurrent(int version) { lock (_syncRoot) { return !_disposed && version == _version; } } private void Run(object state) { while (true) { T value; int version; lock (_syncRoot) { if (_disposed || !_hasPendingValue) { _workerRunning = false; return; } value = _pendingValue; version = _version; _pendingValue = default(T); _hasPendingValue = false; } try { _work(value, version); } catch { // 查询异常由控件自身转换为空结果;这里确保工作循环能够继续或退出。 } } } public void Dispose() { lock (_syncRoot) { _disposed = true; _hasPendingValue = false; _pendingValue = default(T); _version++; } } } }