Asynchronous 如何在Rx中等待

Asynchronous 如何在Rx中等待,asynchronous,system.reactive,Asynchronous,System.reactive,我正在学习被动扩展,这些天我遇到了这种情况,代码如下: class Program { private static void Main(string[] args) { var ls = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ToObservable(); ls.Select(m => new { t = Obser

我正在学习被动扩展,这些天我遇到了这种情况,代码如下:

    class Program
{
    private static void Main(string[] args)
    {
        var ls = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ToObservable();
        ls.Select(m => new
            {
                t = Observable.Start(() =>
                    {
                        Thread.Sleep(100);
                        return new Random().Next(3, 20);
                    }),
                i = m
            }).Subscribe(item => item.t.Subscribe(Console.WriteLine));
        Task.WaitAll();
        Console.WriteLine("all done");
        Console.ReadKey();
    }
}
类程序
{
私有静态void Main(字符串[]args)
{
var ls=新列表{1,2,3,4,5,6,7,8,9}.ToObservable();
ls.选择(m=>new
{
t=可观察。开始(()=>
{
睡眠(100);
返回新的Random()。下一步(3,20);
}),
i=m
}).Subscribe(item=>item.t.Subscribe(Console.WriteLine));
Task.WaitAll();
控制台。写入线(“全部完成”);
Console.ReadKey();
}
}

它显示了在一个可观察对象中有一个IObservable,我想在所有过程完成后打印“全部完成”,但这不起作用。“全部完成”在程序启动后立即打印,不再是等待,在我的情况下,我应该怎么做才能得到真正的等待?

这并不是Rx的工作原理。在
Task.WaitAll()
和您的接收代码之间没有链接。您甚至不会将任何任务传递给
WaitAll()
方法;-)

因此,首先,
Subscribe
方法是非阻塞的。它只是说明此时我想开始使用这个序列,这就是向我发送值/错误/完成通知时要做的事情

你的嵌套可观察序列是一个相当高级的话题,可以直接跳进去,但这没关系,我们可以处理它

class Program
{
    private static void Main(string[] args)
    {
        //Let go, we are not IEnumerable any more :-)
        var ls = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ToObservable();

        var subscription = ls.Select(_ =>
                Observable.Start(() =>
                    {
                        Thread.Sleep(100);
                        return new Random().Next(3, 20);
                    })
             })
            .Merge() //Merge the IO<IO<T>> into Io<T> so we get a single completion.
            .Subscribe(
                item => item.Subscribe(Console.WriteLine),
                ()=>Console.WriteLine("all done"));


        Console.ReadKey();
        subscription.Dispose();
    }
}
类程序
{
私有静态void Main(字符串[]args)
{
//放开,我们不再是数不清的了:-)
var ls=新列表{1,2,3,4,5,6,7,8,9}.ToObservable();
var subscription=ls。选择(\ux=>
可观察。开始(()=>
{
睡眠(100);
返回新的Random()。下一步(3,20);
})
})
.Merge()//将IO合并到IO中,这样我们就可以完成一次。
.订阅(
item=>item.Subscribe(Console.WriteLine),
()=>Console.WriteLine(“全部完成”);
Console.ReadKey();
subscription.Dispose();
}
}
您可以通过将
可观察的.Start
+
线程.Sleep
替换为类似
可观察的.Timer
调度程序的Rx方法来进一步改进代码


这里需要注意的关键是Rx是异步的。关键不在于阻止。此代码中唯一阻塞的是
线程.Sleep
控制台.ReadKey()
。理想情况下,如上所述,您可以替换
线程。无论如何,Sleep

这并不是Rx的工作原理。在
Task.WaitAll()
和您的接收代码之间没有链接。您甚至不会将任何任务传递给
WaitAll()
方法;-)

因此,首先,
Subscribe
方法是非阻塞的。它只是说明此时我想开始使用这个序列,这就是向我发送值/错误/完成通知时要做的事情

你的嵌套可观察序列是一个相当高级的话题,可以直接跳进去,但这没关系,我们可以处理它

class Program
{
    private static void Main(string[] args)
    {
        //Let go, we are not IEnumerable any more :-)
        var ls = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ToObservable();

        var subscription = ls.Select(_ =>
                Observable.Start(() =>
                    {
                        Thread.Sleep(100);
                        return new Random().Next(3, 20);
                    })
             })
            .Merge() //Merge the IO<IO<T>> into Io<T> so we get a single completion.
            .Subscribe(
                item => item.Subscribe(Console.WriteLine),
                ()=>Console.WriteLine("all done"));


        Console.ReadKey();
        subscription.Dispose();
    }
}
类程序
{
私有静态void Main(字符串[]args)
{
//放开,我们不再是数不清的了:-)
var ls=新列表{1,2,3,4,5,6,7,8,9}.ToObservable();
var subscription=ls。选择(\ux=>
可观察。开始(()=>
{
睡眠(100);
返回新的Random()。下一步(3,20);
})
})
.Merge()//将IO合并到IO中,这样我们就可以完成一次。
.订阅(
item=>item.Subscribe(Console.WriteLine),
()=>Console.WriteLine(“全部完成”);
Console.ReadKey();
subscription.Dispose();
}
}
您可以通过将
可观察的.Start
+
线程.Sleep
替换为类似
可观察的.Timer
调度程序的Rx方法来进一步改进代码


这里需要注意的关键是Rx是异步的。关键不在于阻止。此代码中唯一阻塞的是
线程.Sleep
控制台.ReadKey()
。理想情况下,如上所述,您将替换
线程。不管怎样,睡眠

您似乎在这里做一些“非Rx”类型的编码。你试图完成的任务实际上是非常直接的

首先,您有一些代码在完成一些工作后生成值。我将其重新编码为:

var rnd = new Random();
Func<int> produceValue = () =>
{
    Thread.Sleep(100);
    return rnd.Next(3, 20);
};
订阅它也很容易:

query.Subscribe(
    Console.WriteLine,
    () => Console.WriteLine("All Done."));

我想这正是你想要编码的,没有任何讨厌的
WaitFor
代码。

你似乎在做一些“非Rx”类型的编码。你试图完成的任务实际上是非常直接的

首先,您有一些代码在完成一些工作后生成值。我将其重新编码为:

var rnd = new Random();
Func<int> produceValue = () =>
{
    Thread.Sleep(100);
    return rnd.Next(3, 20);
};
订阅它也很容易:

query.Subscribe(
    Console.WriteLine,
    () => Console.WriteLine("All Done."));

我认为这正是您试图编写的代码,没有任何讨厌的
WaitFor
代码。

默认调度程序是否使用任务?我不这么认为。您可能必须在屏幕上进行观察,才能使其正常工作。虽然,无论如何可能不是最好的设计,使用静态任务方法来协调线程。默认调度程序是否使用任务?我不这么认为。您可能必须在屏幕上进行观察,才能使其正常工作。尽管,无论如何,使用静态任务方法来协调线程可能不是最好的设计。