异步等待创建文件

Lie*_*iel 14 .net c# async-await

什么是await外部应用程序创建文件最干净的方法?

    async Task doSomethingWithFile(string filepath)
    {
        // 1. await for path exists
        // 2. Do something with file
    }
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 20

因此,第一个关键点是,FileSystemWatcher当文件系统事件在特定路径发生更改时,您可以使用a 来通知.例如,如果您希望在特定位置创建文件时收到通知,则可以找到答案.

接下来,我们可以创建一个方法,TaskCompletionSource当文件系统观察程序触发相关事件时,该方法使用a 来触发任务的完成.

public static Task WhenFileCreated(string path)
{
    if (File.Exists(path))
        return Task.FromResult(true);

    var tcs = new TaskCompletionSource<bool>();
    FileSystemWatcher watcher = new FileSystemWatcher(Path.GetDirectoryName(path));

    FileSystemEventHandler createdHandler = null;
    RenamedEventHandler renamedHandler = null;
    createdHandler = (s, e) =>
    {
        if (e.Name == Path.GetFileName(path))
        {
            tcs.TrySetResult(true);
            watcher.Created -= createdHandler;
            watcher.Dispose();
        }
    };

    renamedHandler = (s, e) =>
    {
        if (e.Name == Path.GetFileName(path))
        {
            tcs.TrySetResult(true);
            watcher.Renamed -= renamedHandler;
            watcher.Dispose();
        }
    };

    watcher.Created += createdHandler;
    watcher.Renamed += renamedHandler;

    watcher.EnableRaisingEvents = true;

    return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这首先检查文件是否存在,以允许它立即退出(如果适用).它还使用创建的和重命名的处理程序,因为任一选项都可以允许文件在将来的某个时刻存在.它FileSystemWatcher也只是监视目录,因此获取指定路径的目录然后检查事件处理程序中每个受影响文件的文件名很重要.

另请注意,代码在完成后会删除事件处理程序.

这允许我们写:

public static async Task Foo()
{
    await WhenFileCreated(@"C:\Temp\test.txt");
    Console.WriteLine("It's aliiiiiive!!!");
}
Run Code Online (Sandbox Code Playgroud)

  • 这样做有很多问题:永远不会丢弃fsw,如果删除文件然后重新制作,它将出错,他传递文件名而不是目录路径... -1。 (3认同)
  • 如果文件名被编辑怎么办?另外,他想等待特定的文件名。 (2认同)
  • 感谢您修复它。只是一个小问题:仍未解决。 (2认同)
  • 这不是比赛条件吗?我认为,如果文件是在`File.Exists()`检查和`EnableRaisingEvents = true`之间创建的,则`Task'将永远不会完成。 (2认同)
  • 请注意,FileSystemWatcher 将在与您来自的线程不同的线程上引发事件,因此您可能会丢失上下文。有关更多详细信息,请参阅 http://www.roufa.com/articles/async-await-through-the-looking-glass/。 (2认同)
  • @roufamatic当然,但是如果你在一个 UI 上下文中,编组到给定上下文很重要,那么在这种情况下 `await` 将为你处理它,如果你不是,说因为它是一个控制台应用程序,那么在另一个线程中没有问题。不管怎样,这应该不是问题。 (2认同)