【问题标题】:Async queue operations [closed]异步队列操作[关闭]
【发布时间】:2017-03-30 20:59:36
【问题描述】:

我有一个队列,每 x 秒增加一个新元素。

我想对队列中的每个项目执行一个操作。但我想在继续下一个项目之前“消费”一个项目。 每个项目都在进行异步调用,需要在转移到下一个项目之前完成。

我在不阻止应用程序的情况下完成这项工作时遇到问题。任何人都有如何做到这一点的例子?

【问题讨论】:

  • TPL 数据流很容易做到这一点。
  • 你有一个简单的例子来说明如何做到这一点
  • 您如何知道新项目已添加到队列中?你有什么活动吗?

标签: 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 并且事件处理程序的初始调用完成。

通过这个计划,我们永远不会同时有两个“正在运行”的出列项。请记住,“等待”是工作流中的一个点,在该点直到任务完成,工作流才会继续。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多