Kami telah berperang dengan Rusia sejak 24 Februari 2022. Untuk membantu Ukraina mencapai kemenangan sesegera mungkin, mohon abaikan semua produk, perusahaan, proyek Rusia... Semuanya.
Anda juga dapat membantu Angkatan Bersenjata Ukraina di sini: https://bank.gov.ua/en/news/all/natsionalniy-bank-vidkriv-spetsrahunok-dlya-zboru-koshtiv-na-potrebi-armiyi
Kami akan membebaskan Tanah Air kami dari penjajah Rusia dan menyelamatkan Eropa dari rezim Rusia yang agresif dan tidak manusiawi. Saya berjanji.
Jika Anda ingin mendukung saya secara pribadi, Anda dapat melakukannya di sini: https://ko-fi.com/VladPVS
Pustaka .NET multithreading yang memberikan peluang untuk menemukan file atau direktori dengan cepat menggunakan kriteria pencarian berbeda.
Versi .NET Core tersedia di sini.
Alat pencarian file MIF didasarkan pada perpustakaan ini. Anda bisa mencobanya jika ingin memperkirakan kecepatan kerja saat ini.
using FastSearchLibrary;
4.5.1
jika Anda menggunakan perpustakaan v1.1.6.1 atau 4.6.2
jika Anda menggunakan setidaknya v1.1.7.2: Proyek -> Properti -> Kerangka target Kelas berikutnya menyediakan fungsionalitas pencarian:
FileSearcher
dan DirectorySearcher
berisi metode statis yang memungkinkan untuk mengeksekusi pencarian dengan kriteria berbeda. Metode ini mengembalikan hasil hanya ketika eksekusi telah selesai sepenuhnya.string folder
- mulai direktori pencarianstring pattern
- string pencarian yang cocok dengan nama file di jalur. Parameter ini dapat berisi kombinasi jalur literal yang valid dan karakter wildcard (* dan ?), namun tidak mendukung ekspresi reguler.Contoh:
List < FileInfo > files = FileSearcher . GetFiles ( @"C:Users" , " *.txt " ) ;
Temukan semua file *.txt
di C:Users
menggunakan metode satu thread.
List < FileInfo > files = FileSearcher . GetFilesFast ( @"C:Users" , " *SomePattern*.txt " ) ;
Menemukan semua file yang cocok dengan pola yang sesuai menggunakan beberapa utas di kumpulan utas.
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"C:" , " a?.txt " ) ;
Menemukan semua file yang cocok dengan pola yang sesuai menggunakan beberapa thread di kumpulan thread sebagai operasi asinkron.
string folder
- mulai direktori pencarianFunc<FileInfo, bool> isValid
- delegasi yang menentukan algoritma pemilihan file.Contoh:
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"D:" , ( f ) =>
{
return ( f . Name . Contains ( " Pattern " ) || f . Name . Contains ( " Pattern2 " ) ) && f . LastAccessTime >= new DateTime ( 2018 , 3 , 1 ) && f . Length > 1073741824 ;
} ) ;
Menemukan semua file yang cocok dengan kondisi yang sesuai menggunakan beberapa thread di kumpulan thread sebagai operasi asinkron.
Anda juga dapat menggunakan ekspresi reguler:
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"D:" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".*Imagine[s_-]Dragons.*.mp3$" ) ;
} ) ;
Menemukan semua file yang cocok dengan ekspresi reguler yang sesuai menggunakan beberapa thread di kumpulan thread sebagai operasi asinkron.
Jika Anda ingin melakukan pencarian rumit dengan hasil real-time, Anda harus menggunakan instance kelas FileSearcher
, yang memiliki berbagai kelebihan konstruktor. Kelas FileSearcher
mencakup acara berikutnya:
event EventHandler<FileEventArgs> FilesFound
- diaktifkan ketika bagian file berikutnya ditemukan. Acara termasuk List<FileInfo> Files { get; }
properti yang berisi daftar file temuan.event EventHandler<SearchCompleted> SearchCompleted
- diaktifkan ketika proses pencarian selesai atau dihentikan. Acara termasuk bool IsCanceled { get; }
properti yang berisi nilai yang menentukan apakah proses pencarian dihentikan dengan memanggil metode StopSearch()
. Untuk menghentikan kemungkinan proses pencarian kita harus menggunakan konstruktor yang menerima parameter CancellationTokenSource.Contoh:
class Searcher
{
private static object locker = new object ( ) ; // locker object
private FileSearcher searcher ;
private List < FileInfo > files ;
public Searcher ( )
{
files = new List < FileInfo > ( ) ; // create list that will contain search result
}
public void StartSearch ( )
{
CancellationTokenSource tokenSource = new CancellationTokenSource ( ) ;
// create tokenSource to get stop search process possibility
searcher = new FileSearcher ( @"C:" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".*[iI]magine[s_-][dD]ragons.*.mp3$" ) ;
} , tokenSource ) ; // give tokenSource in constructor
searcher . FilesFound += ( sender , arg ) => // subscribe on FilesFound event
{
lock ( locker ) // using a lock is obligatory
{
arg . Files . ForEach ( ( f ) =>
{
files . Add ( f ) ; // add the next part of the received files to the results list
Console . WriteLine ( $" File location: { f . FullName } , n Creation.Time: { f . CreationTime } " ) ;
} ) ;
if ( files . Count >= 10 ) // one can choose any stopping condition
searcher . StopSearch ( ) ;
}
} ;
searcher . SearchCompleted += ( sender , arg ) => // subscribe on SearchCompleted event
{
if ( arg . IsCanceled ) // check whether StopSearch() called
Console . WriteLine ( " Search stopped. " ) ;
else
Console . WriteLine ( " Search completed. " ) ;
Console . WriteLine ( $" Quantity of files: { files . Count } " ) ; // show amount of finding files
} ;
searcher . StartSearchAsync ( ) ;
// start search process as an asynchronous operation that doesn't block the called thread
}
}
Perhatikan bahwa semua event handler FilesFound
tidak aman untuk thread sehingga untuk mencegah kehilangan hasil, seseorang harus menggunakan kata kunci lock
seperti yang Anda lihat pada contoh di atas atau menggunakan koleksi thread aman dari System.Collections.Concurrent
namespace.
Ada 2 parameter tambahan yang dapat diatur. Ini adalah handlerOption
dan suppressOperationCanceledException
. Parameter ExecuteHandlers handlerOption
mewakili contoh enumerasi ExecuteHandlers
yang menentukan di mana event handler FilesFound dijalankan:
InCurrentTask
berarti event handler FileFound
akan dieksekusi dalam tugas tempat file ditemukan.InNewTask
berarti event handler FilesFound
akan dieksekusi dalam tugas baru. Nilai defaultnya adalah InCurrentTask
. Hal ini lebih disukai dalam banyak kasus. Nilai InNewTask
harus digunakan hanya jika penangan menjalankan pekerjaan yang sangat canggih yang memerlukan banyak waktu, misalnya penguraian setiap file yang ditemukan. parameter bool suppressOperationCanceledException
menentukan apakah perlu untuk menekan OperationCanceledException. Jika parameter suppressOperationCanceledException
memiliki nilai false
dan metode StopSearch() disebut OperationCanceledException
akan dilempar. Dalam hal ini Anda harus memproses pengecualian secara manual. Jika parameter suppressOperationCanceledException
memiliki nilai true
dan metode StopSearch() disebut OperationCanceledException
diproses secara otomatis dan Anda tidak perlu menangkapnya. Nilai defaultnya adalah true
.
Contoh:
CancellationTokenSource tokenSource = new CancellationTokenSource ( ) ;
FileSearcher searcher = new FileSearcher ( @"D:Program Files" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".{1,5}[Ss]ome[Pp]attern.txt$" ) && ( f . Length >= 8192 ) ; // 8192b == 8Kb
} , tokenSource , ExecuteHandlers . InNewTask , true ) ; // suppressOperationCanceledException == true
Kelas FileSearcher
dan DirectorySearcher
hanya dapat mencari di satu direktori (dan tentunya di semua subdirektori) tetapi bagaimana jika Anda ingin melakukan pencarian di beberapa direktori secara bersamaan?
Tentu saja, Anda dapat membuat beberapa instance kelas FileSearcher
(atau DirectorySearcher
) dan meluncurkannya secara bersamaan, tetapi peristiwa FilesFound
(atau DirectoriesFound
) akan terjadi untuk setiap instance yang Anda buat. Biasanya, ini merepotkan. Kelas FileSearcherMultiple
dan DirectorySearcherMultiple
dimaksudkan untuk mengatasi masalah ini. Mereka mirip dengan FileSearcher
dan DirectorySearcher
tetapi dapat menjalankan pencarian di beberapa direktori. Perbedaan antara FileSearcher
dan FileSearcherMultiple
adalah konstruktor kelas Multiple
menerima daftar direktori, bukan satu direktori.
Contoh:
List < string > folders = new List < string >
{
@"C:UsersPublic" ,
@"C:WindowsSystem32" ,
@"D:Program Files" ,
@"D:Program Files (x86)"
} ; // list of search directories
List < string > keywords = new List < string > { " word1 " , " word2 " , " word3 " } ; // list of search keywords
FileSearcherMultiple multipleSearcher = new FileSearcherMultiple ( folders , ( f ) =>
{
if ( f . CreationTime >= new DateTime ( 2015 , 3 , 15 ) &&
( f . Extension == " .cs " || f . Extension == " .sln " ) )
{
foreach ( var keyword in keywords )
if ( f . Name . Contains ( keyword ) )
return true ;
}
return false ;
} , tokenSource , ExecuteHandlers . InCurrentTask , true ) ;
Sangat disarankan untuk menggunakan kata kunci "menunggu" saat Anda menggunakan metode asinkron apa pun. Hal ini memungkinkan untuk mendapatkan kemungkinan pengecualian dari metode untuk pemrosesan berikut, yang ditunjukkan pada contoh kode berikutnya. Pemrosesan kesalahan pada contoh sebelumnya telah dilewati demi kesederhanaan.
Contoh:
using System ;
using System . Collections . Generic ;
using System . Diagnostics ;
using System . IO ;
using System . Text . RegularExpressions ;
using System . Threading ;
using FastSearchLibrary ;
namespace SearchWithAwait
{
class Program
{
private static object locker = new object ( ) ;
private static List < FileInfo > files ;
private static Stopwatch stopWatch ;
static void Main ( string [ ] args )
{
string searchPattern = @".mp4$" ;
StartSearch ( searchPattern ) ;
Console . ReadKey ( true ) ;
}
private static async void StartSearch ( string pattern )
{
stopWatch = new Stopwatch ( ) ;
stopWatch . Start ( ) ;
Console . WriteLine ( " Search has been started. n " ) ;
files = new List < FileInfo > ( ) ;
List < string > searchDirectories = new List < string >
{
@"C:" ,
@"D:"
} ;
FileSearcherMultiple searcher = new FileSearcherMultiple ( searchDirectories , ( f ) =>
{
return Regex . IsMatch ( f . Name , pattern ) ;
} , new CancellationTokenSource ( ) ) ;
searcher . FilesFound += Searcher_FilesFound ;
searcher . SearchCompleted += Searcher_SearchCompleted ;
try
{
await searcher . StartSearchAsync ( ) ;
}
catch ( AggregateException ex )
{
Console . WriteLine ( $" Error occurred: { ex . InnerException . Message } " ) ;
}
catch ( Exception ex )
{
Console . WriteLine ( $" Error occurred: { ex . Message } " ) ;
}
finally
{
Console . Write ( " n Press any key to continue... " ) ;
}
}
private static void Searcher_FilesFound ( object sender , FileEventArgs arg )
{
lock ( locker ) // using of the lock is mandatory
{
arg . Files . ForEach ( ( f ) =>
{
files . Add ( f ) ; // add the next part of the received files to the results list
Console . WriteLine ( $" File location: { f . FullName } n Creation.Time: { f . CreationTime } n " ) ;
} ) ;
}
}
private static void Searcher_SearchCompleted ( object sender , SearchCompletedEventArgs arg )
{
stopWatch . Stop ( ) ;
if ( arg . IsCanceled ) // check whether StopSearch() called
Console . WriteLine ( " Search stopped. " ) ;
else
Console . WriteLine ( " Search completed. " ) ;
Console . WriteLine ( $" Quantity of files: { files . Count } " ) ; // show amount of finding files
Console . WriteLine ( $" Spent time: { stopWatch . Elapsed . Minutes } min { stopWatch . Elapsed . Seconds } s { stopWatch . Elapsed . Milliseconds } ms " ) ;
}
}
}
Ada batasan 260 simbol Windows pada nama lengkap file. Dalam kasus umum, perpustakaan akan mengabaikan jalur "panjang" tersebut. Namun jika Anda ingin menghindari batasan ini, Anda harus mengikuti langkah berikutnya:
<Project name>
di Solution explorer, klik tombol kanan mouse -> Add
-> New item
-> Application manifest file
. Kemudian tambahkan konten file ini ke manifes sebelum tag penutup terakhir.HKLMSYSTEMCurrentControlSetControlFileSystem
Kemudian buat parameter LongPathsEnabled
(ketik REG_DWORD) dengan 1
nilai. Itu tergantung pada kinerja komputer Anda, pemuatan saat ini, tetapi biasanya metode Fast
dan metode instan StartSearch()
dilakukan setidaknya 2 kali lebih cepat daripada algoritma rekursif satu thread sederhana.