如何监视和等待文件创建?

问题描述 投票:0回答:1

我正在使用FileSystemWatcher。我从按钮单击事件中调用WatchDirectory。然后,我想分配给label6.Text一旦文件忙于显示“忙”,而当文件不忙时不再显示“不忙”。

并且使用异步,我不确定这是否是正确的方法。这等待的方法是我得到错误。

在WatchDirectory上,我遇到了错误:

找不到'async'修饰符所需的所有类型。您是针对错误的框架版本,还是缺少对程序集的引用?

在行上出现相同错误:返回等待tcs.Task;

在WaitForUnlockedFile上,我得到了错误:

找不到'async'修饰符所需的所有类型。您定位的框架版本错误,还是缺少对程序集的引用?

以及上一个错误:

await Task.Delay(100);

'System.Threading.Tasks.Task'不包含'Delay'的定义

private async Task<string> WatchDirectory()
        {
            using (FileSystemWatcher watcher = new FileSystemWatcher())
            {
                TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();

                watcher.Path = SavePathTextBox.Text;
                watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
                watcher.Filter = "*.jpg";
                watcher.Changed += (sender, e) =>
                {
                    if (e.ChangeType == WatcherChangeTypes.Changed)
                    {
                        var info = new FileInfo(e.FullPath);
                        var theSize = info.Length;
                        label5.BeginInvoke((Action)(() =>
                        {
                            label6.Text = theSize.ToString();
                        }));
                    }
                    tcs.SetResult(e.FullPath);
                };
                watcher.EnableRaisingEvents = true;

                return await tcs.Task;
            }
        }

和WaitForUnlockedFile方法

private async Task WaitForUnlockedFile(string fileName)
    {
        while (true)
        {
            try
            {
                using (IDisposable stream = File.Open(fileName, FileMode.OpenOrCreate,
                    FileAccess.ReadWrite, FileShare.None))
                { /* on success, immediately dispose object */ }

                break;
            }
            catch (IOException)
            {
            }
            await Task.Delay(100);
        }
    }
c# .net winforms async-await filesystemwatcher
1个回答
0
投票

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

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

 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;}


So the first key point is that you can use a FileSystemWatcher to be notified when a file system event changes at a particular path. If you, for example, want to be notified when a file is created at a particular location you can find out.

Next, we can create a method that uses a TaskCompletionSource to trigger the completion of a task when the file system watcher triggers the relevant event.

    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;
    }

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

还请注意,代码完成后会删除事件处理程序。

这使我们可以写:

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

Async wait for file to be created

© www.soinside.com 2019 - 2024. All rights reserved.