c# - ConcurrentQueue 一个元素被两个线程取走

标签 c# multithreading interlocked interlocked-increment

我希望两个线程与一个队列一起工作。第一个线程应该每 2 秒调用一次,第二个线程 - 每 3 秒调用一次。两个线程应同时启动。访问队列的第一个元素时出现问题。两个线程都获取索引为 0 的元素。有时它会发生在队列的其他元素上,而不仅仅是第一个元素。 我在控制台上有这样的输出:

  • 项目 0 由 1 处理时间:3:27:8
  • 项目 0 由 2 处理时间:3:27:8
  • 项目 2 由 1 处理时间:3:27:10
  • 项目 3 由 2 处理时间:3:27:11
  • 项目 4 由 1 处理时间:3:27:12

等等..

这是我使用的代码:

    ConcurrentQueue<int> sharedQueue = new ConcurrentQueue<int>();

    for (int i = 0; i < 10; i++)
    {
        sharedQueue.Enqueue(i);
    }


    int itemCount= 0;


    Task[] tasks = new Task[2];
    for (int i = 0; i < tasks.Length; i++)
    {
        // create the new task
        tasks[i] = new Task(() =>
        {
            while (sharedQueue.Count > 0)
            {
                // define a variable for the dequeue requests
                int queueElement;
                // take an item from the queue
                bool gotElement = sharedQueue.TryDequeue(out queueElement);
                // increment the count of items processed
                if (gotElement)
                {
                    DateTime dt = DateTime.Now;
                    Console.WriteLine("Item " + itemCount + "processed by " 
                        + Task.CurrentId + " Time: " + dt.Hour + ":" + dt.Minute + ":" + dt.Second);
                    Interlocked.Increment(ref itemCount);   
               if (Task.CurrentId == 1) 
                    Thread.Sleep(2000);
                else 
                    Thread.Sleep(3000);                       
                }

            }
        });
        // start the new task
        tasks[i].Start();


    }
    // wait for the tasks to complete
    Task.WaitAll(tasks);
    // report on the number of items processed
    Console.WriteLine("Items processed: {0}", itemCount);
    // wait for input before exiting
    Console.WriteLine("Press enter to finish");
    Console.ReadLine();
}

最佳答案

替换以下行:

Console.WriteLine("Item " + itemCount + "processed by " ...);

用这一行:

Console.WriteLine("Item " + queueElement + "processed by " ...);

您看到的问题可能是由于任务几乎同时执行 Console.WriteLine 并且两者都看到相同的 itemCount 值,因为它们交错以 Interlocked.Increment 调用尚未发生的方式。打印出 queueElement 可能更有意义,因为它更有意义。

关于c# - ConcurrentQueue 一个元素被两个线程取走,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18647678/

相关文章:

c# - Interlocked 是否保证对 C# 中其他线程的可见性,还是我仍然必须使用 volatile?

c# - 在 C# 中打印到 LPT1

c# - 如何将参数从控制台应用程序 c# 传递到正在运行的进程?使用wcf?

c# - 将数字转换为 .NET 中的十六进制值

java - 使用 EasyMock 测试简单的多线程代码,但得到了奇怪的结果

c# - 线程池会不会排队一个定时器的回调函数,有时会同时调度多个线程?

c# - Entity Framework DataContext 问题 - 它是否在我的 Controller 中得到正确处理?

java - Java 监视器的等待集是否优先于入口集?

c# - WPF - 呈现 "Real Time"最佳实践

c# - 将 Interlocked.CompareExchange 与类一起使用