当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《dotNet中是否存在DirectoryInfo.GetFiles/Directory.GetDirectories的异步版本?》经验,为你挑选了3个好方法。

dotNet中是否存在DirectoryInfo.GetFiles/Directory.GetDirectories的异步版本?我想在F#异步块中使用它们,并且拥有一个可以使用AsyncCallbacks调用的版本会很好.

问题是我试图吮吸一堆目录,可能是在慢速网络连接上的SMB挂载上,我不希望一堆线程池线程在等待网络读取时可能正在做其他工作.



1> Juliet..:

我没有找到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) }


当然,这不是真正的异步I/O,但它仍然是一个很好的实用解决方案.如果你确实想要真正的异步操作,你必须使用一些可怕的Win32互操作,我认为这在上下文中是不值得的...

2> Marc Gravell..:

不,我认为没有.池线程方法可能是最实用的.另外,我想你可以下降到的P/Invoke -但是这将是一个很大更多的工作.


现在仍然如此,.NET 4.5出现了一堆新的异步API吗?我一直在寻找这个并没有看到它.

3> Matt Johnson..:

这可能被认为是一种黑客攻击,但您可以考虑使用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


在内部,此库使用什么API?它是否调用* true * -async(重叠的IO?)Win32函数,还是仅将所有内容包装在线程中?
推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有