2

我在我正在处理的 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

4

2 回答 2

3

好的,事实证明,默认情况下,ReplaySubject使用Scheduler.CurrentThread.

如果我明确地将 设置ReplaySubject为使用Scheduler.Immediateor 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 线程是如何在我的特定场景中陷入这种混乱的,但现在,这解决了这个问题。

--- 编辑 ---

OK, on further investigation, it turns out that the above piece of code for most of the time is initiated on a ThreadPool thread. Even though, when it reaches the code, it is on the Dispatcher thread, Scheduler.CurrentThread puts the ReplaySubject back onto the original ThreadPool thread.

However, in the scenario where it is breaking, everything starts with the user clicking a button. This is obviously on the UI thread, and when it reaches this piece of code, Scheduler.CurrentThread is now the UI thread, and since we are already on the UI thread, we have a deadlock. First is waiting for the ReplaySubject to pump - but the pump is queued up behind the current action. Subtle and something of which to be aware.

于 2012-11-07T15:14:33.377 回答
0

从您的代码看来,这里没有注册订阅者Observable。所以它可能会等待一个订阅,这样它就可以给你第一个可用的。

您可以尝试FirstOrDefault查看它是否为空。

于 2012-11-07T13:40:52.037 回答