【问题标题】:ToTask makes OnCompleted execute on different threadToTask 使 OnCompleted 在不同的线程上执行
【发布时间】:2015-08-05 04:40:09
【问题描述】:

代码:

var sc = new TestScheduler();

Observable.Timer(TimeSpan.FromSeconds(5), sc)
          .ToTask()
          .ToObservable()
          .Do(_ => Console.WriteLine("on next: " + Thread.CurrentThread.ManagedThreadId), 
             () => Console.WriteLine("on complete: " + Thread.CurrentThread.ManagedThreadId))
          .Subscribe();

Console.WriteLine("call: " + Thread.CurrentThread.ManagedThreadId);
sc.AdvanceBy(TimeSpan.FromSeconds(5).Ticks);

输出:

call: 11
on next: 8
on complete: 8

如果您同时删除 ToTask 和 ToObservable,那么所有内容都将在同一个线程上执行。在我看来,TPL 以某种方式将 OnCompleted 调度到任务池,但我在源代码中找不到它。

谁能帮我理解这里发生了什么?

DotNetFiddle 链接:https://dotnetfiddle.net/epqTAG

【问题讨论】:

  • 这是你不应该混合你的单子的另一种情况。作为一般规则,您应该将处理保留在 Task<T>IObservable<T> 中,并且仅在绝对需要时才更改 monad。
  • 我有一些服务返回 Task 需要以 Rx 方式处理。所以我在这里真的别无选择。
  • 没关系。如果你绝对需要那么一切都很好。正是这种来回的变化导致了悲伤。

标签: task-parallel-library system.reactive


【解决方案1】:

Task.ToObservable() 使用Task.ContinueWith() 添加一个Task continuation 以在任务完成时触发observable。默认情况下,Task.ContinueWith() 计划在任务池上继续。

Rx.Net 最近添加了一个 ToObservable 的重载,它接受 IScheduler

请参阅 Rx.Net github issue 了解更多详情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 2019-08-14
    • 1970-01-01
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-03-11
    • 1970-01-01
    相关资源
    最近更新 更多