我在我正在工作的Silverlight应用程序中遇到了绝对奇怪的行为。请参阅以下代码:
var replaySubject = new ReplaySubject<string>(1);
replaySubject.OnNext("This can never block... surely?");
var s = replaySubject.First();
Debug.WriteLine(s);
基本上,我的应用程序通过这段代码重复,它总是打印出消息......除了在First()
行中线程阻塞的一个特定场景。
它总是在UI线程上。如果我在First()
的行上设置了一个断点,并使用调试器钻进replaySubject
,我可以在其队列中看到该字符串。
任何人都可以想到会导致First()
调用阻止的任何情况吗?
BTW:这是RX版本1.1.11111
答案 0 :(得分:3)
好的,事实证明,默认情况下,ReplaySubject
使用Scheduler.CurrentThread
。
如果我明确将ReplaySubject
设置为使用Scheduler.Immediate
或Scheduler.ThreadPool
,那么它会按预期工作。
var replaySubject = new ReplaySubject<string>(1, Scheduler.Immediate);
replaySubject.OnNext("This can never block... surely?");
var s = replaySubject.First();
Debug.WriteLine(s);
我仍然需要调查在我的特定场景中UI线程是如何陷入这种混乱的,但是现在,这解决了这个问题。
---编辑---
好的,经过进一步调查,结果发现大部分时间的上述代码都是在ThreadPool线程上启动的。即使它到达代码时,它位于Dispatcher线程上,Scheduler.CurrentThread将ReplaySubject放回原始的ThreadPool线程。
但是,在它破坏的情况下,一切都从用户点击按钮开始。这显然是在UI线程上,当它到达这段代码时,Scheduler.CurrentThread现在是UI线程,因为我们已经在UI线程上,所以我们有一个死锁。首先是等待ReplaySubject泵送 - 但泵在当前操作后面排队等候。微妙的,需要注意的事情。
答案 1 :(得分:0)
从您的代码中可以看出,Observable
上没有注册订阅者。因此它可能会等待一个人订阅,因此它可以为您提供第一个可用的。
您可以尝试FirstOrDefault
来查看它是否为空。