如何管理 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.Run
或 Task.Factory.StartNew
。然后你可以使用Task.WaitAll
或Task.WhenAll
等待它完成。
你的WriteToConsole
方法也是多余的。 Console.Write
访问不需要锁定,因为它已经是线程安全的。它可以简单地写成
private void WriteToConsole(int p)
{
Console.Write(p);
}
我使用 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.Run
或 Task.Factory.StartNew
。然后你可以使用Task.WaitAll
或Task.WhenAll
等待它完成。
你的WriteToConsole
方法也是多余的。 Console.Write
访问不需要锁定,因为它已经是线程安全的。它可以简单地写成
private void WriteToConsole(int p)
{
Console.Write(p);
}