如何在队列中有新项目时进行出队操作。

4
我有一个应用程序,它使用字符串队列(对应于应用程序需要执行的不同任务)。随机时刻队列可能会被填充字符串(有时每分钟几次,但也可能需要几个小时)。
到目前为止,我总是有一个定时器,每隔几秒钟检查队列是否有项目,并将其删除。
我认为必须有比这种方式更好的解决方案。是否有任何方法可以在将项目添加到队列时获取事件或类似的内容?

https://dev59.com/5nA75IYBdhLWcg3wv73A - Habib
你使用的队列是自己实现的吗? - Saverio Terracciano
不,我只是使用了 System.Collections.Queue。 - Sophie
3个回答

5
是的。看一下TPL Dataflow,特别是BufferBlock<T>,它与BlockingCollection做了几乎相同的事情,并通过利用async/await来避免阻塞你的线程的不良副作用。
所以你可以:
void Main()
{
    var b = new BufferBlock<string>();
    AddToBlockAsync(b);
    ReadFromBlockAsync(b);
}

public async Task AddToBlockAsync(BufferBlock<string> b)
{
    while (true)
    {
        b.Post("hello");
        await Task.Delay(1000);
    }
}

public async Task ReadFromBlockAsync(BufferBlock<string> b)
{
    await Task.Delay(10000); //let some messages buffer up...
    while(true)
    {
        var msg = await b.ReceiveAsync();
        Console.WriteLine(msg);
    }
}

2
我会看一下BlockingCollection.GetConsumingEnumerable。该集合默认支持使用队列,并且使用简单的foreach循环自动从队列中取出添加的值,是一个不错的选择。
此外,还有一种重载方法可以提供一个CancellationToken,这意味着您可以干净地退出。

1

你看过 BlockingCollection 吗?GetConsumingEnumerable() 方法允许在消费者上运行一个无限循环,一旦有新项可用,就会产生新项,无需计时器或 Thread.Sleep's:

// 常见:

  BlockingCollection<string> _blockingCollection =
                     new BlockingCollection<string>();

// 生产者

 for (var i = 0; i < 100; i++) 
 {
    _blockingCollection.Add(i.ToString());
    Thread.Sleep(500); // So you can track the consumer synchronization. Remove.
 }

// 消费者:

   foreach (var item in _blockingCollection.GetConsumingEnumerable())
   {
      Debug.WriteLine(item);
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接