等待的FileSystemWatcher结果

时间:2018-10-16 13:06:55

标签: c#

我围绕FileSystemWatcher创建了一个包装器类。该类的目的是等待创建文本文件,然后将其内容读取到其_result字段中。

我想在名为GetResultAsync()的类中添加一个方法,以便调用者可以await来准备好结果,但是我不知道该怎么做。请有人指出我正确的方向吗?

internal class SingleFileWatcher : IDisposable
{
    private readonly string _targetFile;
    private readonly FileSystemWatcher _fileWatcher;
    private string _result = null;

    internal SingleFileWatcher(string theFile)
    {
        _targetFile = theFile;

        _fileWatcher = new FileSystemWatcher();
        _fileWatcher.Path = Path.GetDirectoryName(theFile);
        _fileWatcher.Filter = Path.GetFileName(theFile);
        _fileWatcher.IncludeSubdirectories = false;
        _fileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
        _fileWatcher.Created += FileCreated;

        if (File.Exists(theFile))
        {
            ProcessFile();
        }
        else
        {
            //this must happen after other members have been set
            _fileWatcher.EnableRaisingEvents = true;
        }
    }

    internal Task<string> GetResultAsync()
    {
        //todo
    }

    private void FileCreated(Object sender, FileSystemEventArgs e)
    {
        ProcessFile();
    }

    private void ProcessFile()
    {

        FileStream stream = null;

        //filecreated is raised as soon as the file is created, but the process may still be writing to the file
        while (true)
        {
            try
            {
                stream = new FileStream(_targetFile, FileMode.Open, FileAccess.Read);

                using (var reader = new StreamReader(stream))
                {
                    stream = null;
                    _result = reader.ReadToEnd();
                }

                break;
            }
            catch (IOException)
            {
                Thread.Sleep(TimeSpan.FromMilliseconds(500));
            }
            finally
            {
                stream?.Dispose();
            }
        }
    }

    public void Dispose()
    {
        _fileWatcher.Created -= FileCreated;
        _fileWatcher.Dispose();
    }
}

1 个答案:

答案 0 :(得分:0)

扩展Jeroen Mosterts评论。您的代码应如下所示:

internal Task<string> GetResultAsync()
{
    var tcs = new TaskCompletionSource<string>();
    ProcessFile();
    tcs.TrySetResult(_result);
    return tcs.Task;
}

这非常幼稚,我建议您考虑一下带有异常处理和取消的方案。它们应位于ProcessFile内,使其看起来像Task<string> ProcessFile(TaskCompletionSource<string> tcs)。 要设置例外,请使用tcs.TrySetException(exception)