How can I watch and wait until file is created? [duplicate]

旧街凉风 提交于 2020-05-22 09:58:11

问题


I'm using FileSystemWatcher. I'm calling the WatchDirectory from a button click event. Then i want assign to label6.Text once the file is busy to display "busy" and when the file is not busy any more to display "not busy".

And using async i'm not sure if it's the right way here. This wait the methods are i'm getting errors.

On WatchDirectory i'm getting the error:

Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

Same error on the line: return await tcs.Task;

On WaitForUnlockedFile i'm getting the error:

Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

And last error on :

await Task.Delay(100);

'System.Threading.Tasks.Task' does not contain a definition for '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;
            }
        }

And the WaitForUnlockedFile method

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

回答1:


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

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

Note that this first checks if the file exists, to allow it to exit right away if applicable. It also uses both the created and renamed handlers as either option could allow the file to exist at some point in the future. The FileSystemWatcher also only watches directories, so it's important to get the directory of the specified path and then check the filename of each affected file in the event handler.

Also note that the code removes the event handlers when it's done.

This allows us to write:

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

Async wait for file to be created



来源:https://stackoverflow.com/questions/34241912/how-can-i-watch-and-wait-until-file-is-created

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!