我正在尝试创建一个函数,该函数接收一个Action和一个Timeout,并在Timeout后执行Action。该函数应该是非阻塞的,并且必须是线程安全的。我也非常想避免使用Thread.Sleep()。
到目前为止,我能做到最好的是这样的:
问题在于从回调函数中调用Dispose()可能不安全。我不确定直接结束是否安全,即使定时器在执行其lambda表达式时仍被认为是活动的,但即使如此,我仍然更愿意妥善处理它。
“延迟一次触发”似乎是一个常见的问题,应该有一种简单的方法来解决这个问题,可能是System.Threading中的某个其他库,但目前我能想到的唯一解决方案是修改上述代码,并在间隔上运行专门的清理任务。您有什么建议吗?
到目前为止,我能做到最好的是这样的:
long currentKey = 0;
ConcurrentDictionary<long, Timer> timers = new ConcurrentDictionary<long, Timer>();
protected void Execute(Action action, int timeout_ms)
{
long currentKey = Interlocked.Increment(ref currentKey);
Timer t = new Timer(
(key) =>
{
action();
Timer lTimer;
if(timers.TryRemove((long)key, out lTimer))
{
lTimer.Dispose();
}
}, currentKey, Timeout.Infinite, Timeout.Infinite
);
timers[currentKey] = t;
t.Change(timeout_ms, Timeout.Infinite);
}
问题在于从回调函数中调用Dispose()可能不安全。我不确定直接结束是否安全,即使定时器在执行其lambda表达式时仍被认为是活动的,但即使如此,我仍然更愿意妥善处理它。
“延迟一次触发”似乎是一个常见的问题,应该有一种简单的方法来解决这个问题,可能是System.Threading中的某个其他库,但目前我能想到的唯一解决方案是修改上述代码,并在间隔上运行专门的清理任务。您有什么建议吗?
Thread.Sleep
可能可行。但是如果你有100个操作呢?你真的想创建100个什么也不做,只睡眠的线程吗?这将浪费100兆字节的堆栈空间(以及其他资源)。 - Jim Mischel