如何管理Monitor.Enter

时间:2015-04-23 14:37:01

标签: c# threadpool

我使用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 五 9 6 4 8

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

由于

2 个答案:

答案 0 :(得分:1)

  

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

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

  • 按顺序工作
  • 并行执行后对结果进行排序
  • 不要为订单烦恼

答案 1 :(得分:1)

如果您订购了它,它本身意味着您按顺序处理它。如果希望按顺序完成,则根本不需要线程。

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

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

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