Ton*_*Nam 2 c# multithreading file task-parallel-library
一旦我将所有C驱动器编入索引以进行快速搜索,它就会帮助很多线程搜索文件!唯一的问题是我找到了重复的文件.如果有人能解释我为什么在以下算法中有重复文件,我将不胜感激.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static volatile List<System.IO.FileSystemInfo> files = new List<System.IO.FileSystemInfo> ( );
static readonly object lockFiles = new object ( ); // every time we read or write to files we use this lock
static long numberOfThreadsRuning; // used to determine when we are done. if 0 threads runing it means we are done!
static readonly int max_Number_OF_Threads = 8;
static void Main ( )
{
numberOfThreadsRuning = 0;
// add first task this will increase numberOfThreadsRuning
AddTask ( () => findFiles ( @"C:\Users\Antonio" ) );
// while number of threads running is greater than 0
while ( Interlocked.Read ( ref numberOfThreadsRuning ) > 0 )
Thread.Sleep ( 100 );
}
// start finding files in a new thread
static void AddTask (Action task )
{
// increment numberOfThreadsRuning with a lock
Interlocked.Increment ( ref numberOfThreadsRuning );
Task.Factory.StartNew ( task ).ContinueWith ( x =>
{
// once we are done executing the task decrement number of threads runing
Interlocked.Decrement ( ref numberOfThreadsRuning );
});
}
// recursively start finding files
static void findFiles ( string path )
{
System.IO.FileSystemInfo[ ] subDirAndFiles;
try {
subDirAndFiles = new System.IO.DirectoryInfo (path).GetFileSystemInfos ( );
}
catch { // sometimes we are not able to access some directories so just ignore the error
return;
}
foreach ( var file in subDirAndFiles )
{
lock(lockFiles)
files.Add ( file );
if ( file is System.IO.DirectoryInfo ) // if it is a directory
{
var numTaskRun = Interlocked.Read (ref numberOfThreadsRuning );
if ( numTaskRun < max_Number_OF_Threads )
AddTask ( ( ) => findFiles ( file.FullName ) ); // if there are 8 or less threads running create a new task
else
findFiles ( file.FullName ); // otherwise continue finding files in current thread
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请尝试通过更改静态变量max_Number_OF_Threads来比较使用8个线程VS 1时的速度1.另一种证明我的算法错误的方法是,(files.Length = different number)每次我有超过1个线程时,它总会找到不同数量的文件.
这就是问题:
foreach ( var file in subDirAndFiles )
{
...
AddTask ( ( ) => findFiles ( file.FullName ) );
}
Run Code Online (Sandbox Code Playgroud)
(除了大量的空间,这对我来说真的很难读......还有非传统的方法名称.)
您正在捕获lambda表达式中的循环变量.这意味着(在C#3和4中)变量将在lambda表达式执行时进行计算- 这意味着您可以从稍后的迭代中获取值.
解决方法是将值复制到循环内的"new"变量中:
foreach (var file in subDirAndFiles)
{
var copy = file;
AddTask(() => FindFiles(copy.FullName));
}
Run Code Online (Sandbox Code Playgroud)
这在C#5编译器中已经改变,因此您不需要"复制"变量 - 相反,它就像foreach在每次迭代时声明一个新变量一样,这是一种更自然的方法.
| 归档时间: |
|
| 查看次数: |
169 次 |
| 最近记录: |