118 lines
3.0 KiB
C#
118 lines
3.0 KiB
C#
using System;
|
|
using System.Threading;
|
|
|
|
namespace Lskj.Control
|
|
{
|
|
/// <summary>
|
|
/// 串行处理请求,并在繁忙时只保留最后一次请求。
|
|
/// 用于输入联想控件,避免每次 TextChanged 都创建独立线程。
|
|
/// </summary>
|
|
internal sealed class LatestValueWorker<T> : IDisposable
|
|
{
|
|
private readonly object _syncRoot = new object();
|
|
private readonly Action<T, int> _work;
|
|
private T _pendingValue;
|
|
private bool _hasPendingValue;
|
|
private bool _workerRunning;
|
|
private bool _disposed;
|
|
private int _version;
|
|
|
|
public LatestValueWorker(Action<T, int> 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++;
|
|
}
|
|
}
|
|
}
|
|
}
|