Chciałbym stworzyć wyszukawrkę plików (przeszukiwanie katalogów rekurencyjnie), którą można w każdej chwili zastopować i wznowić - jak się do tego zabrać?
Przy każdej iteracji sprawdzaj, czy nie została wykonana jakaś czynność przez użytkownika - np. wciśnięcie przycisku "Analuj".
Taka opcja ma też ten plus, że obsługa komunikatów spowoduje, że nie nie zablokuje/zamrozi Ci się okno aplikacji, więc użytkownik nie będzie miał wrażenia, że program się zwiesił.
Możesz też zrobić to w osobnym wątku, ale to chyba jest niepotrzebne komplikowanie tematu.
Pisząc wyszukiwarkę miałem na myśli reprezentację klasy a nie program : P
Prawdopodbnie muszę wykorzystać CancelationToken.
O ile Taski nie sprawiają mi problemu, to implementacja tego Tokenu już tak.
Ja wiele wyciągnąłem od tego pana. Polecam kanał ;)
Hm, okej, ale chyba z tego co widzę, to CancelationToken anuluje wątek, a nie pozwala go zatrzymać i wznowić.
Pewnie muszę to jakoś dziwnie zrobić na lockach i waitach.
Cześć,
Powinieneś się zapoznać z programowanie wielowątkowym na MSD:
https://docs.microsoft.com/en-us/dotnet/standard/threading/threading-objects-and-features
https://docs.microsoft.com/en-us/dotnet/api/system.threading.manualresetevent?view=netframework-4.7.2
Tutaj przykładowy kod jak ten problem rozwiązać.
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace FileSearch
{
class Program
{
static ManualResetEvent suspendResetEvent;
static Program()
{
suspendResetEvent = new ManualResetEvent(true);
}
static void Main(string[] args)
{
FileSearch fs = new FileSearch(suspendResetEvent);
fs.DirectoryFound += FileFoundCallback;
fs.StartSearchTask("D:\\", "VBoxRT-x86.dll");
bool signaled = true;
while (true)
{
Console.WriteLine("[Enter] to {0} ", signaled ? "pause" : "continue");
Console.ReadLine();
if (signaled)
suspendResetEvent.Reset();
else suspendResetEvent.Set();
signaled = !signaled;
}
}
private static void FileFoundCallback(object sender, string e)
{
Console.WriteLine("File found in: {0}", e);
}
}
public class FileSearch
{
public EventHandler<string> DirectoryFound;
ManualResetEvent suspendResetEvent;
public FileSearch(ManualResetEvent suspendResetEvent)
{
this.suspendResetEvent = suspendResetEvent;
}
public Task StartSearchTask(string rootDirectory, string fileName)
{
return Task.Factory.StartNew(() =>
{
RecursiveFileSearch(rootDirectory, fileName);
Console.WriteLine("Search End");
});
}
private void RecursiveFileSearch(string currentDirectory, string fileName)
{
// pause ?
suspendResetEvent.WaitOne();
string[] fileNames = Directory.GetFiles(currentDirectory);
foreach (var fName in fileNames)
{
// directory can contain large amount of files,
// therefore this loop can take time to end.
// It is reasonable to check for suspend signal.
suspendResetEvent.WaitOne();
string curFile = Path.GetFileName(fName);
if (curFile == fileName)
{
DirectoryFound?.Invoke(this, currentDirectory);
}
}
// not found in cur directory
// try next dirs
string[] directories = Directory.GetDirectories(currentDirectory);
foreach (var dir in directories)
{
RecursiveFileSearch(dir, fileName);
}
}
}
}
Tak więc rozwiązaniem jak zatrzymać i wznowić wątek jest ManualResetEvent
Pozdr.
Trochę się nad tym głowiłem, ale udało mi się to zaimplementować.
Dzięki za pomoc.