如何管理 Monitor.Enter 的执行顺序

How to manage execution order of Monitor.Enter

我使用 ThreadPool 来执行并发操作。每个操作都成功执行。我还通过 Monitor.Enter 方法锁定该操作,因为如果我不这样做,我就会遇到线程冲突问题。问题是在 运行 我的应用程序之后,我发现操作的执行顺序错误。这是我的代码:

using System.Threading;

private static readonly Object obj = new Object();

public void Test()
{
    List<int> list1 = new List<int>();

    for (int i = 0; i < 10; i++) list1.Add(i);

    int toProcess = list1.Count;

    using (ManualResetEvent resetEvent = new ManualResetEvent(false))
    {
        for (int i = 0; i < list1.Count; i++)
        {
            var idx = i;

            ThreadPool.QueueUserWorkItem(
                new WaitCallback(delegate(object state)
                {
                    WriteToConsole(list1[idx]);

                    if (Interlocked.Decrement(ref toProcess) == 0)
                        resetEvent.Set();

                }), null);
        }

        resetEvent.WaitOne();
    }
}

private void WriteToConsole(int p)
{
    bool lockWasTaken = false;
    var temp = obj;

    Monitor.Enter(temp, ref lockWasTaken);

    Console.Write(p.ToString());

    Monitor.Exit(temp);
}

输出:

0 1个 2个 3个 7 5个 9 6个 4个 8

我应该怎么做才能解决这个错误的订单?

谢谢

What should I do to fix that wrong order?

没有。应该是这样的。当您并行处理项目时,通常无法保证执行顺序。所以你的选择是:

  • 按顺序工作
  • 并行执行后排序结果
  • 根本不用为订单烦恼

如果您按顺序执行,则本质上意味着您正在按顺序处理它。当你希望它按顺序完成时,你根本不需要线程。

就是说,您不必再直接处理线程池了。使用 Task.RunTask.Factory.StartNew。然后你可以使用Task.WaitAllTask.WhenAll等待它完成。

你的WriteToConsole方法也是多余的。 Console.Write 访问不需要锁定,因为它已经是线程安全的。它可以简单地写成

private void WriteToConsole(int p)
{    
    Console.Write(p);    
}