【问题标题】:Async queue operations [closed]异步队列操作[关闭]
【发布时间】:2017-03-30 20:59:36
【问题描述】:
我有一个队列,每 x 秒增加一个新元素。
我想对队列中的每个项目执行一个操作。但我想在继续下一个项目之前“消费”一个项目。
每个项目都在进行异步调用,需要在转移到下一个项目之前完成。
我在不阻止应用程序的情况下完成这项工作时遇到问题。任何人都有如何做到这一点的例子?
【问题讨论】:
标签:
c#
asynchronous
queue
【解决方案1】:
这看起来相当简单。我假设一切都在一个线程上。如果事情在多个线程上,那么你的问题会稍微难一些,但不会更难。
class C
{
bool busy = false;
FancyQueue q;
public C()
{
q = new FancyQueue();
q.Enqueued += HandleEnqueue;
}
Task HandleItem(Item x) { ... }
async void HandleEnqueue()
{
if (busy)
return;
busy = true;
while (!q.Empty)
await HandleItem(q.Dequeue());
busy = false;
}
}
假设队列为空。不知何故,一个新项目到了。事件处理程序被调用。我们设置忙碌标志并提取项目,并等待其处理。我们回到消息循环。假设在我们等待时另一个项目到达。我们进入处理程序,但它被标记为忙,所以我们退出;我们知道该项目将在未来处理。终于第一个item被处理了,所以我们恢复事件处理程序,嘿嘿,队列不为空,继续往下看;我们等待处理队列中的下一个项目。
一旦队列为空,我们将 busy 设置回 false 并且事件处理程序的初始调用完成。
通过这个计划,我们永远不会同时有两个“正在运行”的出列项。请记住,“等待”是工作流中的一个点,在该点直到任务完成,工作流才会继续。