在C#控制台应用程序中,使用System.Reactive.Linq,我试图创建一个observable,其中每个项目是另一个observable进行某些处理的字符串结果。 我使用字符串和字符创建了一个简单的repro。 警告,此示例完全是CONTRIVED,重点是嵌套的.Wait()挂起。
L.Icon
同样,这不是我如何找到许多文件名的后缀。 问题是如何生成一个Observable of strings,其中字符串是从一个完整的observable计算的。
如果我拿出这个代码并单独运行它就可以了。
Syntax error in SQL statement "ALTER USER SET PASSWORD[*] 'newpassword'"; expected "SET, RENAME, ADMIN"; SQL statement:
ALTER USER SET PASSWORD 'newpassword' [42001-195] 42001/42001
异步方法上有嵌套的Wait(),我不明白。
如何编写嵌套的异步observable,我可以生成一个简单的字符串数组?
由于
-John
答案 0 :(得分:5)
您的代码阻塞的原因是您使用ToObservable()
而未指定调度程序。在这种情况下,它将使用CurrentThreadScheduler
。
所以files
observable首先使用当前线程发出OnNext()
[A](发送"file1.doxc"
)。在OnNext()
返回之前,它无法继续迭代。但是,内部fn
可观察 还使用ToObservable()
和Wait()
阻止,直到fn
完成 - 它将排队第一个OnNext()
(将"f"
)发送到当前线程调度程序,但它永远无法发送它,因为现在第一个OnNext()
[A]永远不会返回。
两个简单的修复:
要么像这样更改files
observable:
IObservable<string> files = fileNames.ToObservable(NewThreadScheduler.Default);
或者,避免使用内部Wait()
和SelectMany
(这绝对是更惯用的Rx):
string[] extensions = files.SelectMany(fn =>
{
return fn.ToObservable()
.TakeLast(4)
.ToArray()
.Select(x => new string(x));
})
.ToArray()
.Wait();
// display results etc.
每种方法都有完全不同的执行语义 - 第一种方法将像嵌套循环一样运行,每个内部observable在下一次外部迭代之前完成。由于删除了Wait()
的阻塞行为,因此第二个将更加交错。如果您使用我编写的Spy方法并在ToObservable()
次调用后附加它,您会非常清楚地看到此行为。
答案 1 :(得分:1)
Wait
是一种阻止调用,它与Rx不能很好地混合。我不确定嵌套的失败原因。
假设有异步功能,则可以:
IObservable<string> files = fileNames.ToObservable();
string[] extensions = await files.SelectMany(async fn =>
{
var extension = await fn.ToObservable()
.TakeLast(4)
.ToArray();
return new string(extension);
})
.ToArray();
答案 2 :(得分:1)
詹姆斯已经解决了这个问题,但我建议你的代码完成这样做:
aspect > 1
现在,它仍然有一个 string[] fileNames = { "file1.doxc", "file2.xlsx", "file3.pptx" };
string[] extensions =
(
from fn in fileNames.ToObservable()
from extension in fn.ToObservable().TakeLast(4).ToArray()
select new string(extension)
)
.ToArray()
.Wait();
。理想情况下,你会做这样的事情:
.Wait()
你应该避免所有等待。