同时进行队列和双端队列

问题描述 投票:0回答:2

我正在开发一个项目,需要读取二维码,将其排队,因为它正在排队,另一个任务将数据出列并通过套接字消息将其发送到机器。这一切都是用 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");
    }
}
c# multithreading parallel-processing queue multitasking
2个回答
2
投票

我强烈推荐使用

BlockingCollection
。您遇到的问题称为生产者-消费者问题

BlockingCollection
提供了处理
Producer-Consumer
问题的实现。

具体来说,您还必须考虑:当出队线程变慢并且无法跟上扫描线程(例如由于当时网络缓慢)时会发生什么?

BlockingCollection
将阻塞排队线程,以同步减慢整个进程,基于
BlockingCollection Capacity specified while constructing

此外,您还可以通过使用

ConcurrentQueue
ConcurrentBag
作为底层存储来获得 FIFO 或 LIFO 行为。
BlockingCollection
只是在底层同步集合之上提供“有界”属性。


-2
投票

在进行了一些基准测试之后,看起来通过多个任务/线程同时将项目添加到并发队列比使用非线程安全集合(例如列表)的锁更快。

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. 

} 
© www.soinside.com 2019 - 2024. All rights reserved.