使用Rx枚举所有文件

本文关键字:文件 枚举 Rx 使用 | 更新日期: 2023-09-27 18:24:16

这是我在文件搜索过程中使用具有大量文件(或来自慢速网络文件夹)的列表框时尝试的更具响应性的接口。

IDisposable observer;
IObservable<IList<FileInfo>> bufferedFiles;
ObservableCollection<object> _fileCollection = new ObservableCollection<object>();
public void EnumerateFiles(string myfolder, string filter)
{
    var syncContext = SynchronizationContext.Current;
    DirectoryInfo dir = new DirectoryInfo(myfolder);
    this.bufferedFiles =
     Observable.Buffer(dir.EnumerateFiles(filter, System.IO.SearchOption.AllDirectories)
    .ToObservable(NewThreadScheduler.Default), TimeSpan.FromSeconds(.2), 100, NewThreadScheduler.Default)
    .ObserveOn(syncContext); 
    this.observer = this.bufferedFiles.Subscribe(outputFiles);
}
private void outputFiles(IEnumerable<FileInfo> FI)
{
    foreach (var file in FI)
        _fileCollection.Add(file);
    Debug.Print(_fileCollection.Count.toString());
}

缓冲区说明如下:

将可观察序列的每个元素放入发送的缓冲区当它已经满了或者已经过了一段时间时,它就会退出。

因此,我预计在本地驱动器上,列表框将一次获得100个项目,而在慢速网络上,它将在.2秒内输出缓冲区收集的任何内容(只要它小于100个项目)。我想在其他线程上枚举,同时观察必须在调度器上。

问题是UI已冻结。

使用Rx枚举所有文件

Observable.Interval每隔指定的时间间隔重复一次操作。缓冲区刚好可以实现您的愿望。

private async Task OutputFiles(IEnumerable<object> paths) 
{ 
    foreach (var o in paths) 
    {
         await Task.Delay(1); // Delay so the UI can update the List
        _fileCollection.Add(o); 
    }
    this.observer = Observable.Buffer(
      dir.EnumerateFiles(
         myfile, 
         System.IO.SearchOption.AllDirectories, 
         true).ToObservable(Scheduler.Default), 
      TimeSpan.FromSeconds(.5),                      
      Scheduler.Default)
   .ObserveOn(syncContext)
   .Subscribe(async x => await outputFiles(x));
}