让我在免责声明的前提下,我对多线程非常陌生,可能会遗漏一些明显的东西。
我目前正在使用以下代码处理目录中的所有文件。我的问题是,是否有可能一个线程完成,递减numFilesLeft
,并发现它等于0,因为下一个项目尚未作为工作项添加,而不是因为所有文件都已处理?如果这是可能的,那么确保它不会发生的标准方法是什么?
感谢您的时间。
List<Bar> bars = new List<Bar>();
int numFilesLeft = 0;
ManualResetEvent isWorkDone = new ManualResetEvent(false);
foreach (string dirName in Directory.GetDirectories(@"c:\Temp"))
{
foreach (string file in Directory.GetFiles(dirName))
{
string temp = file;
Interlocked.Increment(ref numFilesLeft);
ThreadPool.QueueUserWorkItem(delegate
{
try
{
List<Bar> results = Process(File.ReadAllText(temp));
if (results.Count > 0)
{
lock (bars) bars.AddRange(results);
}
}
finally
{
if (Interlocked.Decrement(ref numFilesLeft) == 0)
{
isWorkDone.Set();
}
}
});
}
}
isWorkDone.WaitOne();
isWorkDone.Close();
答案 0 :(得分:4)
是的,这是可能的。通常的技巧是为项目本身排队操作添加一个计数:
List<Bar> bars = new List<Bar>();
int numFilesLeft = 0;
ManualResetEvent isWorkDone = new ManualResetEvent(false);
Interlocked.Increment(ref numFilesLeft);
try
{
foreach (string dirName in Directory.GetDirectories(@"c:\Temp"))
{
foreach (string file in Directory.GetFiles(dirName))
{
string temp = file;
Interlocked.Increment(ref numFilesLeft);
ThreadPool.QueueUserWorkItem(delegate
{
try
{
...
}
finally
{
if (Interlocked.Decrement(ref numFilesLeft) == 0)
{
isWorkDone.Set();
}
}
});
}
}
}
finally
{
if (0 == Interlocked.Decrement(ref numFilesLeft))
{
isWorkDone.Set ();
}
}
...
答案 1 :(得分:0)
我的问题是它是否永远如此 线程可以完成, 减少numFilesLeft,找到它 因为下一个项目等于0 尚未添加为工作项目 不是因为所有文件都已存在 处理?
是。因为我们不知道线程何时开始处理。
如果这是可能的,那将是什么 标准方法,以确保它没有 发生?
我们可以使用一个ManualResetEvent数组,然后在主线程中我们将等待所有线程完成他们的工作。
//假设您获得了目录中的文件数。
var fileCount = 10;
ManualResetEvent[] waitHandles = new ManualResetEvent[fileCount];
通过文件填充并创建您已完成的每个线程。此外,将每个ManualResetEvent作为线程状态传递给您初始化的每个线程。
......
ThreadPool.QueueWorkItem(ProcessFile, waitHandles[i]);
.....
在ProcessFile()方法内部重新获得ManualResetEvent。
void ProcessFile(object stateInfo)
{
var waitHandle = stateInfo as ManualResetEvent;
//Do your work here
//finished. Call Reset()
waitHandle.Reset()
}
在主线程中我们等待所有。
WaitHandle.WaitAll(waitHandles);
确保在主线程终止之前处理所有文件。
希望有所帮助。