【发布时间】:2015-07-20 17:33:38
【问题描述】:
我想生成一个可观察的文件,以便可以随时取消文件名的发现。在本示例中,取消会在 1 秒内自动发生。
这是我当前的代码:
class Program
{
static void Main()
{
try
{
RunAsync(@"\\abc\xyz").GetAwaiter().GetResult();
}
catch (Exception exc)
{
Console.Error.WriteLine(exc);
}
Console.Write("Press Enter to exit");
Console.ReadLine();
}
private static async Task RunAsync(string path)
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
await GetFileSource(path, cts);
}
private static IObservable<string> GetFileSource(string path, CancellationTokenSource cts)
{
return Observable.Create<string>(obs => Task.Run(async () =>
{
Console.WriteLine("Inside Before");
foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).Take(50))
{
cts.Token.ThrowIfCancellationRequested();
obs.OnNext(file);
await Task.Delay(100);
}
Console.WriteLine("Inside After");
obs.OnCompleted();
return Disposable.Empty;
}, cts.Token))
.Do(Console.WriteLine);
}
}
我不喜欢我的实现的两个方面(如果有更多 - 请随时指出):
- 我有一个可枚举的文件,但我手动迭代每个文件。我可以以某种方式使用
ToObservable扩展吗? - 我不知道如何使用传递给
Task.Run的cts.Token。必须使用从外部上下文捕获的cts(GetFileSource参数)。我觉得很难看。
这是应该怎么做的吗?一定是更好的方法。
【问题讨论】:
-
这似乎不是一个非常被动的问题,因为您实际上只是在枚举集合。是什么导致取消?您是否看过 Parallel.ForEach 或 PLinq,它们也支持中间迭代取消?
-
这是一个精简的例子。真正的逻辑要复杂得多。
-
作为一般规则 - 如果您发现自己在做
return Disposable.Empty;,那么您几乎可以肯定做错了什么。
标签: c# system.reactive