到RX的文件流抛出InvalidOperationException

时间:2019-07-12 10:18:09

标签: c# observable system.reactive

我已经设置了一个文件监视程序,以便在文件更改时为我创建一个可观察的滴答声流。然后将其用作触发条件,以启动另一个重复的可观察序列,然后从开放流中读取更新的文件内容。

我遇到的问题是,如果文件更新快速连续大批量发生,则代码会在消息中抛出InvalidOperationException

  

该流的先前操作当前正在使用该流。

堆栈跟踪

   at System.IO.StreamReader.CheckAsyncTaskInProgress()
   at System.IO.StreamReader.ReadLineAsync()
   at System.Reactive.Linq.QueryLanguage.StartAsyncImpl[TSource](Func`1 functionAsync, IScheduler scheduler) in D:\a\1\s\Rx.NET\Source\src\System.Reactive\Linq\QueryLanguage.Async.cs:line 676

我的RX管道可能出了什么问题?

    var fileSystemWatcherChanges =
        Observable
            .Using(() =>
                    new FileSystemWatcher(path)
                    {
                        Filter = fileName,
                        EnableRaisingEvents = true
                    },
                fsw =>
                {
                    return Observable
                        .FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                            h => fsw.Changed += h, h => fsw.Changed -= h)
                        .Select(x => Unit.Default);
                });

    // Now we open a new stream on the same file, shift it to the same position as our previous one
    // finished at, so we can continue with live updates
    var messages =
            Observable.Using(
                    () => new FileStream(logFileLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite),
                    fs =>
                    {
                        fs.Seek(_fileStream.Position, SeekOrigin.Begin);

                        return Observable.Using(() => new StreamReader(fs),
                            sr =>
                                fileSystemWatcherChanges
                                    .StartWith(Unit.Default)
                                    .Select(x =>
                                        Observable
                                            .Defer(() => Observable.FromAsync(sr.ReadLineAsync))
                                            .Repeat()
                                            .TakeUntil(w => w == null))
                                    .Merge()
                                    .Where(w => w != null))
                        .Select((x, n) => new LogTailMessage(n, x));
                    });

    _logger.Info($"Started tailing log file for {logFileLocation}");

    Stream = messages
            .Buffer(TimeSpan.FromMilliseconds(500), 100)
            .Replay()
            .RefCount();

0 个答案:

没有答案