C# 使用Rx枚举所有文件
这是我在文件搜索过程中使用大量文件(或来自慢速网络文件夹)创建listbox时尝试的更具响应性的界面C# 使用Rx枚举所有文件,c#,reactive-programming,C#,Reactive Programming,这是我在文件搜索过程中使用大量文件(或来自慢速网络文件夹)创建listbox时尝试的更具响应性的界面 IDisposable observer; IObservable<IList<FileInfo>> bufferedFiles; ObservableCollection<object> _fileCollection = new ObservableCollection<object>(); public void EnumerateFile
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());
}
IDisposable观察员;
IObservable缓冲文件;
ObservableCollection_fileCollection=新的ObservableCollection();
公共文件(字符串myfolder、字符串筛选器)
{
var syncContext=SynchronizationContext.Current;
DirectoryInfo dir=新的DirectoryInfo(myfolder);
此文件为.bufferedFiles=
Observable.Buffer(目录枚举文件(过滤器,System.IO.SearchOption.AllDirectories)
.ToObservable(NewThreadScheduler.Default)、TimeSpan.FromSeconds(.2)、100、NewThreadScheduler.Default)
.ObserveOn(syncContext);
this.observer=this.bufferedFiles.Subscribe(outputFiles);
}
私有void输出文件(IEnumerable FI)
{
foreach(FI中的var文件)
_fileCollection.Add(文件);
Print(_fileCollection.Count.toString());
}
缓冲区的解释如下:
…将可观察序列的每个元素放入已发送的缓冲区中
当它已满或已过给定的时间时退出
所以我希望在本地驱动器上listbox一次可以获得100个项目,而在慢速网络上,它将在0.2秒内输出缓冲区收集的任何内容(只要小于100个项目)。我希望在另一个线程上进行枚举,而观察显然必须在dispatcher上
问题是UI被冻结了 可观察的间隔。每隔指定的时间间隔重复该操作。缓冲区刚好能满足你的愿望
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));
}
专用异步任务输出文件(IEnumerable路径)
{
foreach(路径中的变量o)
{
等待任务。延迟(1);//延迟以便UI可以更新列表
_添加(o);
}
this.observer=Observable.Buffer(
目录文件(
我的文件,
System.IO.SearchOption.AllDirectory,
true)。ToObservable(Scheduler.Default),
时间跨度。从秒(.5),
调度程序(默认)
.ObserveOn(同步上下文)
.Subscribe(异步x=>等待输出文件(x));
}
与哪种代码相比,它的速度较慢?你测试过不止一次吗?当您指定一个时间间隔(TimeSpan)时,它将在该时间间隔过期后开始。如果要立即启动,请指定StartWith(0)。@MartijnvanPut比不使用Rx时慢,只需在ForEach中枚举文件和.Add。为什么不在dir.EnumerateFiles上调用ToObservable并在SyncContext上观察它,然后再次检查性能?我想知道为什么要在枚举文件时使用间隔和Zip/Buffer?这种构造对非对称的情况相同吗-RX@MartijnvanPutStartWith(0)消除了恼人的延迟。谢谢使用Zip/Buffer,我试图强制输出,无论是经过0.2秒还是首先找到1000个项目。这样,用户在.2s之后至少会有一些内容。我做得对吗?间隔每.2秒重复一次,当我正确理解您时,您需要以下内容:dir.EnumerableFiles().ToObservable().Take(1000).TimeSpan.FromSeconds(.2))。此代码接受前1000个或超时(它抛出TimeoutException以便捕获它)