鉴于以下内容:
为什么RECT barRect;
barRect.top = 0;
barRect.left = 0;
barRect.bottom = 100;
barRect.right = 1020;
m_pMainWnd->RepositionBars(0, 0, 0, 2, &barRect);
m_pMainWnd->GetTopLevelFrame()->RecalcLayout();
m_pMainWnd->DrawMenuBar();
for (POSITION pos = m_pMainWnd->GetTopLevelFrame()->m_listControlBars.GetHeadPosition(); pos != NULL;)
{
CControlBar* controlBar = reinterpret_cast<CControlBar*>(m_pMainWnd->GetTopLevelFrame()->m_listControlBars.GetNext(pos));
controlBar = nullptr; //Let's see what we can do with this. Is the menuBar a ControlBar? Didnt think so.
}
m_pMainWnd->RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
中的OnError
处理程序从未调用过?
Subscribe
答案 0 :(得分:5)
当您在令牌上调用Cancel
时,您(通过令牌并因此“拥有”取消的订阅者)基本上说“我不再对事件感兴趣,包括OnError()”。< / p>
在幕后,Rx在observable和观察者之间插入AutoDetachObserver
,显式吞下所有其他事件。
此行为是设计使然。
在您订阅时, OnError()
可以告诉您有关失败的信息。取消令牌(取消订阅观察者)后,您不再订阅并且不再接收任何事件。换句话说,取消订阅不是错误。并且取消observable中的令牌不是错误或是一种有效的通信方式 - 调用OnError()
。
答案 1 :(得分:3)
在观察者OnError
(以及其他函数)的基本实现中包含:
if (Interlocked.Exchange(ref this.isStopped, 1) == 0)
{
this.OnErrorCore(error);
}
值isStopped
设置为&#34;已停止&#34;当令牌取消时。观察员负责取消过程,不需要手动控制它。
如果您将OnNext
代码更改为
if(str == "B")
token.Cancel(); // cancel after the second iteration.
结果将是:
即使您删除了if
语句。取消令牌后,不会调用任何继承的函数
var observable = Observable.Create<string>(
async (o, c) =>
{
var strings = new[] { "A", "B", "C" };
foreach (var s in strings)
{
await Task.Delay(100);
o.OnNext(s);
}
o.OnCompleted();
});
因此,请记住,当令牌被取消时(逻辑上它不是错误)不要将逻辑移动到任何事件实现,而是在调用者代码中执行所需的取消逻辑:
if (c.IsCancellationRequested)
{
// exception thrown here.
Console.WriteLine("cancelled");
tcs.SetResult(true); // instead of throwing exceptions
// some other clean up code or/and return statement
}
答案 2 :(得分:3)
建立詹姆斯所写的内容:Rx订阅的两部分,可观察(发布者)和观察者(订阅者)。当您使用取消令牌订阅到observable时,您有效地告诉订阅者取消订阅。
在您的方案中,这意味着一旦取消,订阅者就会停止收听。因此,onError
通知不会被收听,因此Task
永远不会完成。
如果删除传递给订阅调用的token
,则onError
将按预期流向订阅。