我正在使用的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.ImmediateScheduler.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泵入-但泵在当前操作之后排队。微妙的东西要注意。

08-27 16:34