English 中文(简体)
speeding up windows file search with C#
原标题:

i made a program that search logical drives to find a specific file .if user type file name an click search button , searching begins , but i don t know how to stop searching in the middle of process.can you help me ?

最佳回答

You should perform the search on a background thread so that it doesn t block the UI. This article has a good introduction and walkthrough of the changes that you ll need to make to your app.

问题回答

You need to use Backgroundworker class in .net. It executes on separate thread and it has inbuilt methods/properties for cancellation, report progress and lot more...

Have a look at following article to get started with it:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

You need to run the search in a background thread (Using BackgroundWorker is the most convenient way to do this) then you can still handle input to cancel it.

When you are handling the cancel request you may need to use Thread.Abort on the executing thread or BackgroundWorker.CancelAsync() on the BackgroundWorker.

Alternatively you can have the executing thread check a variable while in the processing loop or at the start of a recursive function - to cancel you simple need to set this variable when handling the cancel request.

As others have mentioned, your solution may be to use BackgroundWorker with CancelAsync method.

Here is some working code which you could use with minor modifications:

class Program
{
    static void Main(string[] args)
    {
        var search = new FileSearcher().FindFile(@"d:users", "autofac.dll", f => Console.WriteLine(f.FullName), () => Console.WriteLine("Finished"));

        Console.WriteLine("C - cancel, else - finish");

        for (; ; )
        {
            var command = Console.ReadLine();
            switch (command)
            {
                case "C":
                    search.Cancel();
                    break;

                default:
                    return;
            }
        }
    }
}

public class FileSearcher
{
    public FileSearch FindFile(string searchPath, string fileName, Action<FileInfo> onFileFound, Action onSearchFinished)
    {
        var search = new FileSearch(new DirectoryInfo(searchPath), fileName);
        search.FileFound += onFileFound;
        search.Finished += onSearchFinished;
        search.Run();
        return search;
    }
}

public class FileSearch
{
    readonly BackgroundWorker _worker = new BackgroundWorker();
    readonly DirectoryInfo _searchPath;
    readonly string _template;

    public FileSearch(DirectoryInfo searchPath, string template)
    {
        _searchPath = searchPath;
        _template = template;

        _worker.DoWork += _worker_DoWork;
        _worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
        _worker.WorkerSupportsCancellation = true;
    }

    void _worker_DoWork(object sender, DoWorkEventArgs e)
    {
        foreach (var directory in GetPartiallyFlatDirectories(_searchPath, 4))
        {
            if (_worker.CancellationPending)
                break;

            foreach (var file in directory.GetFiles(_template, SearchOption.AllDirectories))
                FileFound.Raise(file);
        }
    }

    static IEnumerable<DirectoryInfo> GetPartiallyFlatDirectories(DirectoryInfo directory, int flatDepth)
    {
        if (flatDepth == 0)
        {
            yield return directory;
            yield break;
        }

        foreach (var subDir in directory.GetDirectories())
        {
            var flattened = GetPartiallyFlatDirectories(subDir, flatDepth - 1);

            if (!flattened.Any())
                yield return subDir;
            else
                foreach (var flatDirectory in flattened)
                    yield return flatDirectory;
        }
    }

    void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Finished.Raise();
    }

    public void Cancel()
    {
        _worker.CancelAsync();
    }

    public event Action<FileInfo> FileFound;
    public event Action Finished;

    public void Run()
    {
        _worker.RunWorkerAsync();
    }
}

public static class DelegateExtensions
{
    public static void Raise<T>(this Action<T> action, T obj)
    {
        if (action != null)
            action(obj);
    }

    public static void Raise(this Action action)
    {
        if (action != null)
            action();
    }
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签