Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何确保在响应式扩展中同步调用Select和Subscribe方法_C#_System.reactive - Fatal编程技术网

C# 如何确保在响应式扩展中同步调用Select和Subscribe方法

C# 如何确保在响应式扩展中同步调用Select和Subscribe方法,c#,system.reactive,C#,System.reactive,我正在测试RX并创建Stream(),它提供两个相隔1秒的事件 private IObservable<string> Stream() { return Observable.Create<string> ( (IObserver<string> observer) => { observer.OnNext("a"); observer.OnNext("b"

我正在测试RX并创建Stream(),它提供两个相隔1秒的事件

private IObservable<string> Stream()
{
    return Observable.Create<string>
    (
        (IObserver<string> observer) =>
        {
            observer.OnNext("a");
            observer.OnNext("b");
            observer.OnCompleted();         
            return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
        }
    );
}

  _refreshFiberStream =
    Stream()
    .SubscribeOn(schedulerProvider.EventLoop) 
    .Select(DoCalc)
    .ObserveOn(schedulerProvider.Dispatcher)
    .Subscribe(Update);
我看到每个输入都会调用DoCalc方法两次,然后是Update方法调用两次,DoCalc,DoCalc,Update,Update。相反,我尝试执行DoCalc方法后面跟着Update方法的顺序。重复第二次输入的顺序,以便第二次输入可以建立在第一次输入的结果之上,DoCalc,Update,DoCalc,Update


任何想法

首先,我会遵循将SubscribeOn/ObserveOn对放在最终订阅方法之前的模式。这只会帮你省去很多麻烦

_refreshFiberStream = Stream()
    .Select(DoCalc)
    //Always in this pattern
    .SubscribeOn(schedulerProvider.EventLoop) //SubscribeOn right before ObserveOn (or before Subscribe if no ObserveOn is used)
    .ObserveOn(schedulerProvider.Dispatcher)  //ObserveOn right before Subscribe
    .Subscribe(Update);                       //Subscribe Last
接下来,如果我重新创建您的示例并添加缺少的代码,我将获得正确/预期的输出

void Main()
{
    var els = new EventLoopScheduler();
    var dispatcher = new EventLoopScheduler();

    Stream()
        .SubscribeOn(els) //TODO: Move to line just before ObserveOn
        .Select(DoCalc)
        .ObserveOn(dispatcher)
        .Subscribe(Update); 
}

// Define other methods and classes here
private IObservable<string> Stream()
{
    return Observable.Create<string>
    (
        (IObserver<string> observer) =>
        {
            observer.OnNext("a");
            Thread.Sleep(1000);
            observer.OnNext("b");
            observer.OnCompleted();         
            return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
        }
    );
}
private string DoCalc(string val)
{
    val.Dump("DoCalc()");
    Thread.Sleep(1000);
    return val;
}
private void Update(string val)
{
    val.Dump("Update()");
}
void Main()
{
var els=新的EventLoopScheduler();
var dispatcher=new EventLoopScheduler();
流()
.SubscribeOn(els)//TODO:移动到ObserveOn之前的行
.选择(DoCalc)
.ObserveOn(调度员)
.订阅(更新);
}
//在此处定义其他方法和类
私有IObservable流()
{
返回可观察的。创建
(
(IObserver观察员)=>
{
OnNext观察员(“a”);
睡眠(1000);
OnNext观察员(“b”);
observer.OnCompleted();
返回Disposable.Create(()=>Console.WriteLine(“观察者已取消订阅”);
}
);
}
私有字符串DoCalc(字符串val)
{
val.Dump(“DoCalc()”);
睡眠(1000);
返回val;
}
私有无效更新(字符串val)
{
val.Dump(“更新()”);
}
因此,您可以用输出重新发布完整的示例代码。作为单元测试、控制台应用程序或LinqPad示例执行此操作


猜测您的下一个问题,可能是:如何使用投影中的值(
选择
)来帮助计算下一个值?如果需要,请使用
Scan
方法;如果只需要最终结果,而不是计算的每个值,请使用
Aggregate
方法。

能否提供
scheduleProvider
的代码?如果我删除了
SubscribeOn
ObserveOn
行,那么我看到了您想要的行为。您可以删除线程吗?在DoCalc中睡眠并尝试运行。你会得到DoCalc,DoCalc,然后是Update,Update,而不是DoCalc,Update,DoCalc,UpdateCorrect。这就是我所期望的。Create委托正在
SubscribeOn
计划程序上运行,并将
OnNext
直接发送到
Select
处理程序,该处理程序是
DoUpdate
DoUpdate的结果是序列的结果投影。然后将这些值调度到最终订阅处理程序。如果您需要这些值进行序列化,那么不要强制在另一个Select投影中执行两组计划,或者执行更新中的操作。如果您可以进一步解释为什么需要这些值,也许我可以提供更好的帮助。e、 g.为什么这些重叠是一个问题?
void Main()
{
    var els = new EventLoopScheduler();
    var dispatcher = new EventLoopScheduler();

    Stream()
        .SubscribeOn(els) //TODO: Move to line just before ObserveOn
        .Select(DoCalc)
        .ObserveOn(dispatcher)
        .Subscribe(Update); 
}

// Define other methods and classes here
private IObservable<string> Stream()
{
    return Observable.Create<string>
    (
        (IObserver<string> observer) =>
        {
            observer.OnNext("a");
            Thread.Sleep(1000);
            observer.OnNext("b");
            observer.OnCompleted();         
            return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
        }
    );
}
private string DoCalc(string val)
{
    val.Dump("DoCalc()");
    Thread.Sleep(1000);
    return val;
}
private void Update(string val)
{
    val.Dump("Update()");
}