有没有更好的方法来限制高吞吐量作业?

2024-02-23

我创建了一个简单的类,它展示了我正在尝试做的事情,没有任何噪音。 请随意攻击我的代码。这就是我将其发布在这里的原因。

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();
            }
        }
    }
}

首先,我会完全摆脱控制线程,因为它的工作可以在调用之前轻松完成work().

然后,我将使工作线程与主线程不同,从而为其他任务解除主线程的阻塞。接下来,我将添加一个函数来取消处理,这可能会设置一个检查工作线程的标志。

Edit:
根据评论,我们的目标是限制数量work()每次通话期间throttlePeriod滴答声。我们可以通过记下秒表中的时间来做得更好,然后进行比较throttleLimit工作操作,剩下的时间就是睡觉。这样我们就不再需要计时器线程了。

编辑:(已删除,不正确)
Edit:
我们甚至可以做某种平衡:处于一个throttlePeriod,我们计算花了多少时间work()花费,所以我们可以估计剩余的时间work()s 将采取并等待each two work()剩余时间均等。这将使我们无法执行所有work()在分配周期开始时速度非常快,可能会阻塞数据库。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有更好的方法来限制高吞吐量作业? 的相关文章

随机推荐