gpt4 book ai didi

c# - 确保长时间运行的任务只触发一次,后续请求排队但队列中只有一个条目

转载 作者:太空狗 更新时间:2023-10-29 23:31:03 25 4
gpt4 key购买 nike

我有一个计算密集型方法Calculate,它可能会运行几秒钟,请求来自多个线程。

应该只执行一个Calculate,后续请求应该排队直到初始请求完成。如果已经有一个请求排队,则可以丢弃后续请求(因为排队的请求就足够了)

似乎有很多潜在的解决方案,但我只需要最简单的。

更新:这是我的初步尝试:

private int _queueStatus;
private readonly object _queueStatusSync = new Object();

public void Calculate()
{
lock(_queueStatusSync)
{
if(_queueStatus == 2) return;
_queueStatus++;
if(_queueStatus == 2) return;
}
for(;;)
{
CalculateImpl();
lock(_queueStatusSync)
if(--_queueStatus == 0) return;

}
}

private void CalculateImpl()
{
// long running process will take a few seconds...
}

最佳答案

IMO 最简单、最干净的解决方案是使用 TPL Dataflow(一如既往)和一个 BufferBlock 作为队列。 BufferBlock 是线程安全的,支持async-await,更重要的是,有TryReceiveAll 可以一次获取所有项目。它还具有 OutputAvailableAsync,因此您可以异步等待将项目发布到缓冲区。当发布多个请求时,您只需选择最后一个而忘记其余的:

var buffer = new BufferBlock<Request>();
var task = Task.Run(async () =>
{
while (await buffer.OutputAvailableAsync())
{
IList<Request> requests;
buffer.TryReceiveAll(out requests);
Calculate(requests.Last());
}
});

用法:

buffer.Post(new Request());
buffer.Post(new Request());

编辑:如果您没有Calculate 方法的任何输入或输出,您可以简单地使用boolean 来充当转变。如果为真,您可以将其关闭并计算,如果在 Calculate 运行时再次为真,则再次计算:

public bool _shouldCalculate;

public void Producer()
{
_shouldCalculate = true;
}

public async Task Consumer()
{
while (true)
{
if (!_shouldCalculate)
{
await Task.Delay(1000);
}
else
{
_shouldCalculate = false;
Calculate();

}
}
}

关于c# - 确保长时间运行的任务只触发一次,后续请求排队但队列中只有一个条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25190381/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com