簡體   English   中英

dotNet中是否存在DirectoryInfo.GetFiles / Directory.GetDirectories的異步版本?

[英]Is there an async version of DirectoryInfo.GetFiles / Directory.GetDirectories in dotNet?

dotNet中是否存在DirectoryInfo.GetFiles / Directory.GetDirectories的異步版本? 我想在F#異步塊中使用它們,並且擁有一個可以使用AsyncCallbacks調用的版本會很好。

問題是我試圖吮吸一堆目錄,可能是在慢速網絡連接上的SMB掛載上,我不希望一堆線程池線程在等待網絡讀取時可能正在做其他工作。

我沒有找到GetFiles的異步版本,但是如果你查看其他異步操作的源代碼,它們的定義如下:

module FileExtensions =

        let UnblockViaNewThread f =
            async { //let ctxt = System.Threading.SynchronizationContext.Current
                    do! Async.SwitchToNewThread ()
                    let res = f()
                    do! Async.SwitchToThreadPool ()
                    //do! Async.SwitchTo ctxt
                    return res }

        type System.IO.File with
            static member AsyncOpenText(path)   = UnblockViaNewThread (fun () -> System.IO.File.OpenText(path))
            static member AsyncAppendText(path) = UnblockViaNewThread (fun () -> System.IO.File.AppendText(path))
            static member AsyncOpenRead(path)   = UnblockViaNewThread (fun () -> System.IO.File.OpenRead(path))
            static member AsyncOpenWrite(path)  = UnblockViaNewThread (fun () -> System.IO.File.OpenWrite(path))
            static member AsyncOpen(path,mode,?access,?share) =
                let access = match access with Some v -> v | None -> System.IO.FileAccess.ReadWrite
                let share = match share with Some v -> v | None -> System.IO.FileShare.None
                UnblockViaNewThread (fun () -> System.IO.File.Open(path,mode,access,share))

            static member OpenTextAsync(path)   = System.IO.File.AsyncOpenText(path)
            static member AppendTextAsync(path) = System.IO.File.AsyncAppendText(path)
            static member OpenReadAsync(path)   = System.IO.File.AsyncOpenRead(path)
            static member OpenWriteAsync(path)  = System.IO.File.AsyncOpenWrite(path)
            static member OpenAsync(path,mode,?access,?share) = System.IO.File.AsyncOpen(path, mode, ?access=access, ?share=share)

換句話說,Async文件,streamreader和WebClient操作只是同步操作的包裝器,因此您應該能夠在GetFiles / GetDirectories周圍編寫自己的包裝器,如下所示:

module IOExtensions =
    type System.IO.Directory with
        static member AsyncGetFiles(directory) = async { return System.IO.Directory.GetFiles(directory) }
        static member AsyncGetDirectories(path) = async { return System.IO.Directory.GetDirectories(path) }

不,我認為沒有。 池線程方法可能是最實用的。 另外,我想你可以下降到的P / Invoke -但是這將是大量的工作。

這可能被認為是一種黑客攻擊,但您可以考慮使用UWP StorageFolder API

C#示例(雖然F#可能同樣容易):

using Windows.Storage;

...

var folder = await StorageFolder.GetFolderFromPathAsync(path);
var files = await folder.GetFilesAsync();
var folders = await folder.GetFoldersAsync();

您可以使用Lucian Wischik(Microsoft)的UWP for Desktop庫輕松地從傳統的.NET桌面和控制台應用程序中使用這些內容。

Install-Package UwpDesktop

實際上,根據Directory.GetFiles幫助Directory.EnumerateFiles將立即返回第一個結果(它是一個IEnumerable ),而不是在返回之前等待整個列表。 我相信這可能就是你要找的東西。

我已經多次使用這種方法從函數/過程中獲取Async對象,它總是很好用:


let AsyncGetDirectories path = 
    let fn = new Func<_, _>(System.IO.Directory.GetDirectories)
    Async.BuildPrimitive(path, fn.BeginInvoke, fn.EndInvoke)

我不是F#程序員,但我會在C#中這樣做:

static IEnumerable<string> IterateFiles(string path, string pattern) {
    var entryQueue = new Queue<string>();
    entryQueue.Enqueue(path);

    while (entryQueue.Count > 0) {
        var subdirs = Directory.GetDirectories(entryQueue.Peek());
        var files = Directory.GetFiles(entryQueue.Peek(), pattern, SearchOption.TopDirectoryOnly);
        foreach (var file in files)
            yield return file;
        entryQueue.Dequeue();

        foreach(var subdir in subdirs)
            entryQueue.Enqueue(subdir);
    }
}

我假設在F#中有一個與迭代器類似的構造。

Princess的答案是在任務之間添加粒度的方法 - 所以這種事情會讓其他玩家使用線程池:

let! x = OpenTextAsync("whatever");
// opening for something else to run
let! x = OpenTextAsync("whatever");
// opening for something else to run
let! x = OpenTextAsync("whatever");

當這些阻塞調用中的每一個都很重時,它沒有多大幫助 - 而且基於SMB的GetFiles幾乎就是沉重的定義。

我希望有一些BeginRead / EndRead的目錄,並且GetFiles / GetDirectories只是一個很好的包裝,可以解決暴露一些異步變種的低級調用。 BeginReadDir / EndReadDir類的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM