Asynchroniczne wyszukawnie plików z kontrolą procesu.

0

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ć?

0

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.

0

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.

1

Ja wiele wyciągnąłem od tego pana. Polecam kanał ;)

https://m.youtube.com/watch?v=ZTKGRJy5P2M&t=449s

0

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.

1

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.

0

Trochę się nad tym głowiłem, ale udało mi się to zaimplementować.

Dzięki za pomoc.

1 użytkowników online, w tym zalogowanych: 0, gości: 1