首页 > 解决方案 > 如何填充队列并同时打印?

问题描述

我目前正在用消息填充队列系统。当新消息开始进入时,应该有一个单独的线程打印队列。问题是我的程序不工作。

private static void pData(IWebDriver driver)
{
    Queue<string> messageToSend = new Queue<string>();

    Thread printThread = new Thread(new ParameterizedThreadStart(PrintQueueMessages));
    printThread.Start(messageToSend);

    while (true)
    {
        messageToSend.Enqueue(GetLastElement(driver).Text));
    }
}

private static void PrintQueueMessages(object messageQueue)
{
    //Wont let me cast messageQueue as queue. 
}

当我的 while 循环填满我的队列时,我只想要一种简单而干净的方式来打印我的队列。此外,队列系统应该继续等待消息,它不应该停止等待消息并打印它们。

请注意:排队系统应按自己的时间运行。当消息进来时,它应该打印出来。

标签: c#multithreading

解决方案


我将建议一种完全不同的方法,而不是 BCL 队列,(在这种情况下)无界通道将是一个不错的选择

优点是

  • 您无需同步队列和工作负载以及永久的 while 循环即可在多线程环境中工作。
  • 它经过优化且重量轻
  • 它将处理多个线程
  • 是可以取消的
  • 可以完成
  • 它使用(并且会很好地工作)async 和 await 模式IO 工作负载

给定

private static Channel<string> _channel;

public static async Task ReaderAsync(CancellationToken cancellationToken)
{
   // read from the channel until complete
   await foreach (var message in _channel.Reader.ReadAllAsync(cancellationToken))
      Console.WriteLine("New message : " + message);

   Console.WriteLine("Finished");
}

测试

var ts = new CancellationTokenSource();

_channel = Channel.CreateUnbounded<string>();

// start the reader task
var task = ReaderAsync(ts.Token);

// post some junk to the channel, this can be on a different thread
for (var i = 0; i < 10; i++)
{
   // some delay for the fun of it
   await Task.Delay(10, ts.Token);
   // write to the channel
   await _channel.Writer.WriteAsync(i.ToString(), ts.Token);
}

 // complete it when and if you are finished
_channel.Writer.Complete();

// just awaiting completion for this demo
await task;

Console.WriteLine("Game over");

输出

New message : 0
New message : 1
New message : 2
New message : 3
New message : 4
New message : 5
New message : 6
New message : 7
New message : 8
New message : 9
Finished
Game over

推荐阅读