เราอยู่ในภาวะสงครามกับรัสเซียตั้งแต่วันที่ 24 กุมภาพันธ์ พ.ศ. 2565 เพื่อช่วยให้ยูเครนได้รับชัยชนะโดยเร็วที่สุด โปรดเพิกเฉยต่อผลิตภัณฑ์ บริษัท โครงการทั้งหมดของรัสเซีย... ทุกสิ่งทุกอย่าง
นอกจากนี้คุณยังสามารถช่วยเหลือกองทัพยูเครนได้ที่นี่: https://bank.gov.ua/en/news/all/natsionalniy-bank-vidkriv-spetsrahunok-dlya-zboru-koshtiv-na-potrebi-armiyi
เราจะปลดปล่อยมาตุภูมิของเราจากผู้รุกรานชาวรัสเซียและช่วยยุโรปจากระบอบการปกครองรัสเซียที่ไร้มนุษยธรรมที่ก้าวร้าว ฉันสัญญา.
หากคุณต้องการสนับสนุนฉันเป็นการส่วนตัว สามารถทำได้ที่นี่: https://ko-fi.com/VladPVS
ไลบรารี .NET แบบมัลติเธรดที่ให้โอกาสในการค้นหาไฟล์หรือไดเร็กทอรีอย่างรวดเร็วโดยใช้เกณฑ์การค้นหาที่แตกต่างกัน
เวอร์ชัน .NET Core มีให้ที่นี่
เครื่องมือค้นหาไฟล์ MIF ขึ้นอยู่กับไลบรารีนี้ คุณสามารถลองใช้ได้หากต้องการประมาณความเร็วของงานตอนนี้
using FastSearchLibrary;
4.5.1
หากคุณใช้ v1.1.6.1 ของไลบรารีหรือ 4.6.2
หากคุณใช้อย่างน้อย v1.1.7.2: โครงการ -> คุณสมบัติ -> กรอบงานเป้าหมาย คลาสถัดไปมีฟังก์ชันการค้นหา:
FileSearcher
และ DirectorySearcher
มีเมธอดสแตติกที่อนุญาตให้ดำเนินการค้นหาตามเกณฑ์ที่แตกต่างกัน วิธีการเหล่านี้จะส่งคืนผลลัพธ์เฉพาะเมื่อดำเนินการเสร็จสิ้นแล้วเท่านั้นstring folder
- เริ่มไดเร็กทอรีการค้นหาstring pattern
- สตริงการค้นหาที่จะจับคู่กับชื่อไฟล์ในพาธ พารามิเตอร์นี้สามารถประกอบด้วยพาธลิเทอรัลที่ถูกต้องและอักขระตัวแทน (* และ ?) ที่ถูกต้องร่วมกัน แต่ไม่รองรับนิพจน์ทั่วไปตัวอย่าง:
List < FileInfo > files = FileSearcher . GetFiles ( @"C:Users" , " *.txt " ) ;
ค้นหาไฟล์ *.txt
ทั้งหมดใน C:Users
โดยใช้วิธีเธรดเดียว
List < FileInfo > files = FileSearcher . GetFilesFast ( @"C:Users" , " *SomePattern*.txt " ) ;
ค้นหาไฟล์ทั้งหมดที่ตรงกับรูปแบบที่เหมาะสมโดยใช้หลายเธรดในกลุ่มเธรด
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"C:" , " a?.txt " ) ;
ค้นหาไฟล์ทั้งหมดที่ตรงกับรูปแบบที่เหมาะสมโดยใช้หลายเธรดในเธรดพูลเป็นการดำเนินการแบบอะซิงโครนัส
string folder
- เริ่มไดเร็กทอรีการค้นหาFunc<FileInfo, bool> isValid
- ผู้รับมอบสิทธิ์ที่กำหนดอัลกอริทึมของการเลือกไฟล์ตัวอย่าง:
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 ;
} ) ;
ค้นหาไฟล์ทั้งหมดที่ตรงกับเงื่อนไขที่เหมาะสมโดยใช้หลายเธรดในเธรดพูลเป็นการดำเนินการแบบอะซิงโครนัส
คุณยังสามารถใช้นิพจน์ทั่วไปได้:
Task < List < FileInfo > > task = FileSearcher . GetFilesFastAsync ( @"D:" , ( f ) =>
{
return Regex . IsMatch ( f . Name , @".*Imagine[s_-]Dragons.*.mp3$" ) ;
} ) ;
ค้นหาไฟล์ทั้งหมดที่ตรงกับนิพจน์ทั่วไปที่เหมาะสมโดยใช้หลายเธรดในเธรดพูลเป็นการดำเนินการแบบอะซิงโครนัส
หากคุณต้องการดำเนินการค้นหาที่ซับซ้อนด้วยผลลัพธ์แบบเรียลไทม์ คุณควรใช้อินสแตนซ์ของคลาส FileSearcher
ซึ่งมีคอนสตรัคเตอร์โอเวอร์โหลดมากมาย คลาส FileSearcher
รวมถึงเหตุการณ์ถัดไป:
event EventHandler<FileEventArgs> FilesFound
- เริ่มทำงานเมื่อพบส่วนถัดไปของไฟล์ เหตุการณ์ประกอบด้วย List<FileInfo> Files { get; }
คุณสมบัติที่มีรายการไฟล์การค้นหาevent EventHandler<SearchCompleted> SearchCompleted
- เริ่มทำงานเมื่อกระบวนการค้นหาเสร็จสิ้นหรือหยุดลง เหตุการณ์รวมถึง bool IsCanceled { get; }
คุณสมบัติที่มีค่าที่กำหนดว่ากระบวนการค้นหาหยุดโดยการเรียกเมธอด StopSearch()
หรือไม่ หากต้องการหยุดความเป็นไปได้ของกระบวนการค้นหา เราต้องใช้ตัวสร้างที่ยอมรับพารามิเตอร์ CancellationTokenSourceตัวอย่าง:
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
}
}
โปรดทราบว่าตัวจัดการเหตุการณ์ FilesFound
ทั้งหมดไม่ปลอดภัยสำหรับเธรด ดังนั้นเพื่อป้องกันการสูญเสียผลลัพธ์ควรใช้คีย์เวิร์ด lock
ดังที่คุณเห็นในตัวอย่างด้านบน หรือใช้การรวบรวมเธรดที่ปลอดภัยจาก System.Collections.Concurrent
namespace
มีพารามิเตอร์เพิ่มเติมอีก 2 รายการที่สามารถตั้งค่าได้ เหล่านี้คือ handlerOption
และ suppressOperationCanceledException
OperationCanceledException พารามิเตอร์ ExecuteHandlers handlerOption
แสดงถึงอินสแตนซ์ของการแจงนับ ExecuteHandlers
ที่ระบุตำแหน่งที่ตัวจัดการเหตุการณ์ FilesFound ถูกดำเนินการ:
InCurrentTask
หมายความว่าตัวจัดการเหตุการณ์ FileFound
จะถูกดำเนินการในงานที่พบไฟล์InNewTask
หมายความว่าตัวจัดการเหตุการณ์ FilesFound
จะถูกดำเนินการในงานใหม่ ค่าเริ่มต้นคือ InCurrentTask
จะดีกว่าในกรณีส่วนใหญ่ ค่า InNewTask
ควรใช้เฉพาะเมื่อตัวจัดการรันงานที่ซับซ้อนมากซึ่งใช้เวลานาน เช่น การแยกวิเคราะห์ไฟล์แต่ละไฟล์ที่พบ พารามิเตอร์ bool suppressOperationCanceledException
กำหนดว่าจำเป็นต้องระงับ OperationCanceledException หรือไม่ ถ้าพารามิเตอร์ suppressOperationCanceledException
มีค่า false
และเมธอด StopSearch() ถูกเรียกว่า OperationCanceledException
จะถูกส่งออก ในกรณีนี้ คุณต้องประมวลผลข้อยกเว้นด้วยตนเอง หากพารามิเตอร์ suppressOperationCanceledException
มีค่า true
และเมธอด StopSearch() เรียกว่า OperationCanceledException
จะถูกประมวลผลโดยอัตโนมัติ และคุณไม่จำเป็นต้องตรวจจับมัน ค่าเริ่มต้นเป็น true
ตัวอย่าง:
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
คลาส FileSearcher
และ DirectorySearcher
สามารถค้นหาได้เฉพาะในไดเร็กทอรีเดียวเท่านั้น (และในไดเร็กทอรีย่อยทั้งหมดด้วย) แต่ถ้าคุณต้องการค้นหาในหลาย ๆ ไดเร็กทอรีในเวลาเดียวกันล่ะ?
แน่นอน คุณสามารถสร้างบางอินสแตนซ์ของคลาส FileSearcher
(หรือ DirectorySearcher
) และเปิดใช้งานพร้อมกันได้ แต่เหตุการณ์ FilesFound
(หรือ DirectoriesFound
) จะเกิดขึ้นสำหรับแต่ละอินสแตนซ์ที่คุณสร้าง ตามกฎแล้วจะไม่สะดวก Class FileSearcherMultiple
และ DirectorySearcherMultiple
มีวัตถุประสงค์เพื่อแก้ไขปัญหานี้ คล้ายกับ FileSearcher
และ DirectorySearcher
แต่สามารถดำเนินการค้นหาได้ในหลายไดเรกทอรี ความแตกต่างระหว่าง FileSearcher
และ FileSearcherMultiple
คือ Constructor ของ Multiple
class ยอมรับรายการไดเร็กทอรีแทนไดเร็กทอรีเดียว
ตัวอย่าง:
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 ) ;
ขอแนะนำให้ใช้คำสำคัญ "รอ" เมื่อคุณใช้วิธีการอะซิงโครนัสใดๆ อนุญาตให้รับข้อยกเว้นที่เป็นไปได้จากวิธีการประมวลผลต่อไปนี้ ซึ่งจะแสดงตัวอย่างโค้ดถัดไป การประมวลผลข้อผิดพลาดในตัวอย่างก่อนหน้านี้ถูกข้ามไปเพื่อความเรียบง่าย
ตัวอย่าง:
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 " ) ;
}
}
}
มีข้อจำกัดของ Windows 260 สัญลักษณ์ในชื่อเต็มของไฟล์ ในไลบรารีเคสทั่วไปจะละเว้นพาธ "ยาว" ดังกล่าว แต่หากคุณต้องการหลีกเลี่ยงข้อจำกัดนี้ คุณควรทำตามขั้นตอนถัดไป:
<Project name>
ใน Solution explorer คลิกปุ่มขวาของเมาส์ -> Add
-> New item
-> Application manifest file
จากนั้นเพิ่มเนื้อหาของไฟล์นี้ลงในรายการก่อนแท็กปิดสุดท้ายHKLMSYSTEMCurrentControlSetControlFileSystem
จากนั้นสร้างพารามิเตอร์ LongPathsEnabled
(ประเภท REG_DWORD) ด้วยค่า 1
ขึ้นอยู่กับประสิทธิภาพของคอมพิวเตอร์ของคุณ การโหลดในปัจจุบัน แต่โดยทั่วไปแล้ววิธีการ Fast
และวิธีการแบบอินสแตนซ์ StartSearch()
จะดำเนินการได้เร็วกว่าอัลกอริทึมแบบเรียกซ้ำแบบเธรดเดียวแบบธรรมดาอย่างน้อย 2 เท่า