using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace DotNet4_ParallelSamples
{
using dir = System.IO.Directory;
abstract class FileFinder
{
public IEnumerable<string> FindFiles(string dir_path, string filenameHint)
{
Action<string> addItem;
var filesFound = CreateResultBuffer(out addItem);
FindFilesCore(dir_path, filenameHint, addItem);
return filesFound;
}
protected string[] GetFiles(string dir_path)
{
var files = new string[0];
try
{
files = dir.GetFiles(dir_path);
}
/* ignore */
catch (UnauthorizedAccessException) { }
catch (System.IO.IOException) { }
/* ignore */
return files;
}
protected string[] GetDirectories(string dir_path)
{
var directories = new string[0];
try
{
directories = dir.GetDirectories(dir_path);
}
/* ignore */
catch (UnauthorizedAccessException) { }
catch (System.IO.IOException) { }
/* ignore */
return directories;
}
protected abstract IEnumerable<string> CreateResultBuffer(out Action<string> addFunc);
protected abstract void FindFilesCore(string dir_path, string filenameHint, Action<string> addToResult);
}
class SequentialFileFinder : FileFinder
{
protected override IEnumerable<string> CreateResultBuffer(out Action<string> addFunc)
{
var buffer = new List<string>();
addFunc = buffer.Add;
return buffer;
}
protected override void FindFilesCore(string dir_path, string filenameHint, Action<string> addToResult)
{
foreach (var file in GetFiles(dir_path))
{
if (file.Contains(filenameHint))
{
addToResult(file);
}
}
foreach (var directory in GetDirectories(dir_path))
{
FindFilesCore(directory, filenameHint, addToResult);
}
}
}
class ParallelFileFinder : FileFinder
{
protected override void FindFilesCore(string dir_path, string filenameHint, Action<string> addToResult)
{
Parallel.ForEach(GetFiles(dir_path), (file) =>
{
if (file.Contains(filenameHint))
{
addToResult(file);
}
});
Parallel.ForEach(GetDirectories(dir_path), (directory) =>
{
FindFilesCore(directory, filenameHint, addToResult);
});
}
protected override IEnumerable<string> CreateResultBuffer(out Action<string> addFunc)
{
var buffer = new ConcurrentBag<string>();
addFunc = buffer.Add;
return buffer;
}
}
}
#include <windows.h>
#include <ppl.h>
using namespace Concurrency;
#include <list>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
#include "_helper.hpp"
struct Directory
{
static void GetDirectories( __in const wchar_t* path, __out list<wstring>& directories )
{
EnumIOItems( path, [&]( __in const WIN32_FIND_DATA& ffd )
{
if ( ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && L'.' != ffd.cFileName[0] )
directories.push_back( wstring( path ).append( ffd.cFileName ).append( L"\\" ) );
});
}
static void GetFiles( __in const wchar_t* path, __out list<wstring>& files )
{
EnumIOItems( path, [&]( __in const WIN32_FIND_DATA& ffd )
{
if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
files.push_back( wstring( path ).append( ffd.cFileName ) );
});
}
private:
template<class Function>
static void EnumIOItems( __in const wchar_t* path, __in Function _Func )
{
WIN32_FIND_DATA ffd = { NULL };
HANDLE hFind = FindFirstFile( wstring( path ).append(L"*").c_str(), &ffd );
if ( INVALID_HANDLE_VALUE != hFind )
{
do _Func( ffd ); while( 0 != FindNextFile( hFind, &ffd ) );
FindClose( hFind );
}
}
};
class FileFinder
{
public:
typedef list<wstring> result_type;
typedef result_type& result_type_ref;
FileFinder(){}
virtual ~FileFinder(){}
void FindFiles( __in const wchar_t* path, __in const wchar_t* filenameHint, __out result_type_ref filesFound )
{
FindFilesCore( path, filenameHint, filesFound );
}
protected:
void GetFiles( __in const wchar_t* path, __out result_type_ref files ) const
{
Directory::GetFiles( path, files );
}
void GetDirectories( __in const wchar_t* path, __out result_type_ref directories ) const
{
Directory::GetDirectories( path, directories );
}
template<class Container, class Item> void add( Container& c, const Item& i ) const { c.push_back( i ); }
virtual void FindFilesCore( __in const wchar_t* path, __in const wchar_t* filenameHint, __out result_type_ref filesFound ) const = 0;
};
class SequentialFileFinder : public FileFinder
{
protected:
virtual void FindFilesCore( __in const wchar_t* path, __in const wchar_t* filenameHint, __out result_type_ref filesFound ) const
{
list<wstring> files;
GetFiles( path, files );
for_each( files.begin(), files.end(), [&]( __in const wstring& file )
{
if( wstring::npos != file.find( filenameHint ) )
add( filesFound, file );
} );
list<wstring> directories;
GetDirectories( path, directories );
for_each( directories.begin(), directories.end(), [&]( __in const wstring& dir )
{
FindFilesCore( dir.c_str(), filenameHint, filesFound );
} );
}
};
class ParallelFileFinder : public FileFinder
{
protected:
virtual void FindFilesCore( __in const wchar_t* path, __in const wchar_t* filenameHint, __out result_type_ref filesFound ) const
{
combinable<result_type> filesFound_partial;
list<wstring> files;
parallel_for_each( files.begin(), files.end(), [&]( __in const wstring& file )
{
if( wstring::npos != file.find( filenameHint ) )
add( filesFound_partial.local(), file ); //<-
} );
join( filesFound_partial, filesFound ); //<-
list<wstring> directories;
GetDirectories( path, directories );
parallel_for_each( directories.begin(), directories.end(), [&]( __in const wstring& dir )
{
FindFilesCore( dir.c_str(), filenameHint, filesFound );
} );
}
private:
void join( __in combinable<result_type>& filesFound_partial, __out result_type_ref filesFound ) const
{
filesFound_partial.combine_each( [&](result_type_ref local)
{
copy( local.begin(), local.end(), back_insert_iterator<result_type>( filesFound ) );
local.clear();
} );
}
};

Da mesma forma, o uso de uma estrutura simples de tipos mantém a lista de nomes do seu projeto limpa e clara. Compare o visualizador de classes em projetos Windows com algo mais C++ para ter uma ideia.