2015-08-04 3 views
1

Код:ToTask делает OnCompleted выполнить на другом потоке

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 для Task Pool каким-то образом, но я не могу найти его в исходном коде.

Может кто-нибудь помочь мне понять, что здесь происходит?

DotNetFiddle ссылка: https://dotnetfiddle.net/epqTAG

+0

Это еще один случай, когда вы не должны смешивать свои монады. Как правило, вы должны сохранить свою обработку в «Задаче » или в «IObservable » и только изменить монады, если вам это абсолютно необходимо. – Enigmativity

+0

У меня есть некоторые службы, возвращающие задачу , которые необходимо обрабатывать по Rx. Поэтому у меня нет выбора. – ionoy

+0

Все в порядке. Если вам абсолютно необходимо, то все хорошо. Это меняется взад и вперед, что вызывает горе. – Enigmativity

ответ

3

Task.ToObservable() использует Task.ContinueWith() для добавления задач продолжения, чтобы вызвать наблюдаемый после завершения задачи. По умолчанию Task.ContinueWith() планирует продолжение в пуле задач.

Rx.Net недавно добавил (а) перегрузку ToObservable, которая принимает IScheduler.

Для получения более подробной информации см. Rx.Net github issue.

Смежные вопросы