【发布时间】:2010-03-11 23:27:29
【问题描述】:
我创建了一个简单的类,它显示了我正在尝试做的事情而没有任何噪音。 随意抨击我的代码。这就是我在这里发布它的原因。
public class Throttled : IDisposable
{
private readonly Action work;
private readonly Func<bool> stop;
private readonly ManualResetEvent continueProcessing;
private readonly Timer throttleTimer;
private readonly int throttlePeriod;
private readonly int throttleLimit;
private int totalProcessed;
public Throttled(Action work, Func<bool> stop, int throttlePeriod, int throttleLimit)
{
this.work = work;
this.stop = stop;
this.throttlePeriod = throttlePeriod;
this.throttleLimit = throttleLimit;
continueProcessing = new ManualResetEvent(true);
throttleTimer = new Timer(ThrottleUpdate, null, throttlePeriod, throttlePeriod);
}
public void Dispose()
{
throttleTimer.Dispose();
((IDisposable)continueProcessing).Dispose();
}
public void Execute()
{
while (!stop())
{
if (Interlocked.Increment(ref totalProcessed) > throttleLimit)
{
lock (continueProcessing)
{
continueProcessing.Reset();
}
if (!continueProcessing.WaitOne(throttlePeriod))
{
throw new TimeoutException();
}
}
work();
}
}
private void ThrottleUpdate(object state)
{
Interlocked.Exchange(ref totalProcessed, 0);
lock (continueProcessing)
{
continueProcessing.Set();
}
}
}
最新代码
public class Throttled
{
private readonly Func<bool> work;
private readonly ThrottleSettings settings;
private readonly Stopwatch stopwatch;
private int totalProcessed;
public Throttled(Func<bool> work, ThrottleSettings settings)
{
this.work = work;
this.settings = settings;
stopwatch = new Stopwatch();
}
private void Execute()
{
stopwatch.Start();
while (work())
{
if (++totalProcessed > settings.Limit)
{
var timeLeft = (int)(settings.Period - stopwatch.ElapsedMilliseconds);
if (timeLeft > 0)
{
Thread.Sleep(timeLeft);
}
totalProcessed = 0;
stopwatch.Reset();
stopwatch.Start();
}
}
}
}
【问题讨论】:
-
您的代码缺少启动执行的公共方法。
-
你不需要保护
ManualResetEvent:根据文档(msdn.microsoft.com/en-us/library/…),它是线程安全的。 -
@Vlad - 在任何一种情况下,它似乎都打开了主线程在一段时间内不工作的可能性。关于如何解决这个问题的任何想法?
-
你可以让控制线程不被定时器唤醒,而是等待(其他)事件的信号状态。
-
@Chaos,Timer 类的分辨率与 Sleep 完全相同。是的,大约是 20 毫秒。
标签: c# .net synchronization