这是我尝试在文件搜索过程中使用大量文件(或来自慢速网络文件夹)进行化妆列表框时更具响应性的界面。
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被冻结了。
答案 0 :(得分:2)
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));
}