我正在使用的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()
调用在此处阻止的任何情况吗?顺便说一句:它是RX版本1.1.11111
最佳答案
好的,因此事实证明,默认情况下,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泵入-但泵在当前操作之后排队。微妙的东西要注意。