.net NET 4.0中的Parallel.ForEach private static Int64 DirectoryBytes(字符串路径) { var files=目录.枚举文件(路径); Int64 masterTotal=0; ParallelLoopResult结果=Parallel.ForEach( 文件夹, () => {//localInit:每个任务在开始时调用一次 //初始化此任务已看到0个字节 返回0;//将taskLocalTotal初始值设置为0 }, (文件、循环状态、索引、taskLocalTotal)=> {//body:每个工作项调用一次 //获取此文件的大小并将其添加到此任务的运行总数 Int64 fileLength=0; FileStream fs=null; 尝试 { fs=File.OpenRead(文件); fileLength=fs.Length; } catch(IOException){/*忽略任何我们无法访问的文件*/} 最后{if(fs!=null)fs.Dispose();} 返回taskLocalTotal+fileLength; }, taskLocalTotal=> {//localFinally:每个任务在结束时调用一次 //以原子方式将此任务的总数添加到“主”总数中 联锁。添加(参考masterTotal、taskLocalTotal); }); 返回总数; }
这是我从一本书中得到的一段代码。我对此表示怀疑。 变量.net NET 4.0中的Parallel.ForEach private static Int64 DirectoryBytes(字符串路径) { var files=目录.枚举文件(路径); Int64 masterTotal=0; ParallelLoopResult结果=Parallel.ForEach( 文件夹, () => {//localInit:每个任务在开始时调用一次 //初始化此任务已看到0个字节 返回0;//将taskLocalTotal初始值设置为0 }, (文件、循环状态、索引、taskLocalTotal)=> {//body:每个工作项调用一次 //获取此文件的大小并将其添加到此任务的运行总数 Int64 fileLength=0; FileStream fs=null; 尝试 { fs=File.OpenRead(文件); fileLength=fs.Length; } catch(IOException){/*忽略任何我们无法访问的文件*/} 最后{if(fs!=null)fs.Dispose();} 返回taskLocalTotal+fileLength; }, taskLocalTotal=> {//localFinally:每个任务在结束时调用一次 //以原子方式将此任务的总数添加到“主”总数中 联锁。添加(参考masterTotal、taskLocalTotal); }); 返回总数; },.net,multithreading,parallel-processing,task-parallel-library,.net,Multithreading,Parallel Processing,Task Parallel Library,这是我从一本书中得到的一段代码。我对此表示怀疑。 变量tasklocaltotal将处于线程级别或任务级别。按照书中的说法,它是任务级别的,但是由于一个线程可以执行多个任务,因此变量在整个程序执行过程中保持其值的原因就不同了。 我认为它应该是线程级别的 是否有人可以提供有关这一点的见解,以及可能的更多链接,以便我更清楚地了解这一概念。此处使用的参数指定最后一个参数是为每个已结束的任务调用的操作 因此,在每个任务结束时,任务的结果将传递给Interlocked.Add方法,该方法使用该任务的本地总
tasklocaltotal
将处于线程级别或任务级别。按照书中的说法,它是任务级别的,但是由于一个线程可以执行多个任务,因此变量在整个程序执行过程中保持其值的原因就不同了。
我认为它应该是线程级别的
是否有人可以提供有关这一点的见解,以及可能的更多链接,以便我更清楚地了解这一概念。此处使用的参数指定最后一个参数是为每个已结束的任务调用的操作
因此,在每个任务结束时,任务的结果将传递给Interlocked.Add方法,该方法使用该任务的本地总计来增加masterTotal
令人困惑的是这一部分:
private static Int64 DirectoryBytes(String path)
{
var files = Directory.EnumerateFiles(path);
Int64 masterTotal = 0;
ParallelLoopResult result = Parallel.ForEach<String, Int64>(
files,
() =>
{ // localInit: Invoked once per task at start
// Initialize that this task has seen 0 bytes
return 0; // Set taskLocalTotal initial value to 0
},
(file, loopState, index, taskLocalTotal) =>
{ // body: Invoked once per work item
// Get this file's size and add it to this task's running total
Int64 fileLength = 0;
FileStream fs = null;
try
{
fs = File.OpenRead(file);
fileLength = fs.Length;
}
catch (IOException) { /* Ignore any files we can't access */ }
finally { if (fs != null) fs.Dispose(); }
return taskLocalTotal + fileLength;
},
taskLocalTotal =>
{ // localFinally: Invoked once per task at end
// Atomically add this task's total to the "master" total
Interlocked.Add(ref masterTotal, taskLocalTotal);
});
return masterTotal;
}
只要把它想成(你甚至可以写成):
不幸的是,taskLocalTotal在此处与任务操作中的名称相同
所以它不是同一个变量,而是同一个名称。@Vabs-没问题。顺便问一下,你注意到我的答案链接到的MSDN页面包含几乎完全相同的代码了吗?是的。是的。这本书可能使用MSDN代码示例作为生成示例的基础。
taskLocalTotal =>
{
// localFinally: Invoked once per task at end
// Atomically add this task's total to the "master" total
Interlocked.Add(ref masterTotal, taskLocalTotal);
}
x =>
{
// localFinally: Invoked once per task at end
// Atomically add this task's total to the "master" total
Interlocked.Add(ref masterTotal, x);
}