我正在开发一个项目,需要读取二维码,将其排队,因为它正在排队,另一个任务将数据出列并通过套接字消息将其发送到机器。这一切都是用 C# 完成的。
我的问题是当另一个任务出队时如何保持队列。我有 QR 码工作,我可以排队和出队,并且套接字消息部分工作。但我不知道如何同时运行队列和出队。
我研究了线程,特别是多线程。我比开始阅读之前更困惑了。
任何帮助将不胜感激。
编辑:因此,根据您的评论并做了一些研究,我开始编写一些代码。无论我做什么,线程都只运行一次。它应该继续运行。
public partial class Form1 : Form
{
private BlockingCollection<string> _queue = new BlockingCollection<string>(30);
//private string item = "A";
//private int count = 0;
private Thread _th1;
public Form1()
{
InitializeComponent();
_th1 = new Thread(thread_example);
_th1.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void thread_example()
{
if (_queue.Count > 0)
{
_queue.Take();
Console.WriteLine("Removed 1 Item from queue!");
}
else
{
Console.WriteLine("Queue Empty!");
}
Thread.Sleep(500);
}
private void btnProduce_Click(object sender, EventArgs e)
{
_queue.Add("test_string");
Console.WriteLine("Added 1 item to the queue");
}
}
BlockingCollection
。您遇到的问题称为生产者-消费者问题
BlockingCollection
提供了处理 Producer-Consumer
问题的实现。
具体来说,您还必须考虑:当出队线程变慢并且无法跟上扫描线程(例如由于当时网络缓慢)时会发生什么?
BlockingCollection
将阻塞排队线程,以同步减慢整个进程,基于BlockingCollection Capacity specified while constructing
。
此外,您还可以通过使用
ConcurrentQueue
或 ConcurrentBag
作为底层存储来获得 FIFO 或 LIFO 行为。 BlockingCollection
只是在底层同步集合之上提供“有界”属性。
在进行了一些基准测试之后,看起来通过多个任务/线程同时将项目添加到并发队列比使用非线程安全集合(例如列表)的锁更快。
ConcurrentQueue<>集合可用于具有非锁定和线程安全能力的生产者-消费者场景。不同的线程可以同时进行排队和出队,而无需竞争条件。例如,多个线程可以对项目进行排队,而一个或多个消费者线程可以定期将项目出队以便同时并发处理。
请注意,如果出队时存在太多排队争用,则出队总数很可能会更少,因为仍在添加项目。不用担心,虽然不会丢失任何项目,并且它们可以在后续的双端队列操作中进行轮询/出队。
例如:
//imagine some tasks/threads keep adding items to concurrentqueue and below code (just a simplified version for demonstration) working on a separate thread to poll queue at the same time.
while(true)
{
while (concurrentQueue.TryDequeue(out var item))
{
list.Add(item);
} //when this nested loop ends there might be newly added items to concurrentQueue, they will be picked at next loop.
}