Разница между вашим ожидаемым поведением и фактическим поведением происходит из следующей строки:
var subject = new ReplaySubject<string>();
По умолчанию ReplaySubject
использует Scheduler.CurrentThread
. Это как если бы вы объявили это так:
var subject = new ReplaySubject<string>(Scheduler.CurrentThread);
При планировании с использованием текущего потока вы ставите свои действия в очередь - ожидая завершения выполняющегося в данный момент кода до того, как запустится. Если вы хотите, чтобы код запускался немедленно, вам нужно использовать Scheduler.Immediate
примерно так:
var subject = new ReplaySubject<string>(Scheduler.Immediate);
Достаточно ли это объяснить?