C# 基本线程池问题
让我先声明一下,我对多线程非常陌生,可能遗漏了一些明显的东西 我目前正在使用下面的代码来处理目录中的所有文件。我的问题是,如果一个线程能够完成,减量C# 基本线程池问题,c#,.net-2.0,threadpool,C#,.net 2.0,Threadpool,让我先声明一下,我对多线程非常陌生,可能遗漏了一些明显的东西 我目前正在使用下面的代码来处理目录中的所有文件。我的问题是,如果一个线程能够完成,减量numFilesLeft,并发现它等于0,因为下一个项目没有被添加为工作项目,也不是因为所有文件都已被处理?如果这是可能的,什么是标准的方法来确保它不会发生 谢谢你抽出时间 List<Bar> bars = new List<Bar>(); int numFilesLeft = 0; ManualResetEvent isWo
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();
列表栏=新列表();
int numFilesLeft=0;
ManualResetEvent isWorkDone=新的ManualResetEvent(错误);
foreach(Directory.GetDirectories(@“c:\Temp”)中的字符串dirName)
{
foreach(Directory.GetFiles(dirName))中的字符串文件)
{
字符串temp=文件;
联锁增量(参考numFilesLeft);
ThreadPool.QueueUserWorkItem(委托
{
尝试
{
列表结果=进程(File.ReadAllText(temp));
如果(results.Count>0)
{
锁定(条)条。添加范围(结果);
}
}
最后
{
if(联锁减量(参考numFilesLeft)==0)
{
isWorkDone.Set();
}
}
});
}
}
isWorkDone.WaitOne();
isWorkDone.Close();
是的,这是可能的。通常的诀窍是再增加一个计数,以便对项目本身进行排队操作:
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 ();
}
}
...
列表栏=新列表();
int numFilesLeft=0;
ManualResetEvent isWorkDone=新的ManualResetEvent(错误);
联锁增量(参考numFilesLeft);
尝试
{
foreach(Directory.GetDirectories(@“c:\Temp”)中的字符串dirName)
{
foreach(Directory.GetFiles(dirName))中的字符串文件)
{
字符串temp=文件;
联锁增量(参考numFilesLeft);
ThreadPool.QueueUserWorkItem(委托
{
尝试
{
...
}
最后
{
if(联锁减量(参考numFilesLeft)==0)
{
isWorkDone.Set();
}
}
});
}
}
}
最后
{
如果(0==联锁减量(参考numFilesLeft))
{
isWorkDone.Set();
}
}
...
1。
我的问题是,这是否会发生
一根线可能完成,
减小numFilesLeft,并找到它
等于0,因为下一项
尚未作为工作项添加,并且
不是因为所有的文件都被删除了
处理
对。因为我们不知道线程何时开始处理
2.
如果这是可能的,那么结果会是什么
确保其不发生故障的标准方法
发生了什么
我们可以使用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);
这将确保在主线程终止之前处理所有文件
希望有帮助。这实际上与我以前使用的类似,但我遇到了WaitAll的限制,一次只能等待64个句柄。谢谢。这似乎是一个很好的解决方案。