等待过程从Observable开始

时间:2018-07-03 22:45:28

标签: c# .net async-await system.reactive

我创建了以下代码。我以为它可以用,但不能用。等待无限期地挂在那里(永远不会调用退出事件)。

我不带任何参数调用“ ping”,所以它几乎立即结束。

using System;
using System.Diagnostics;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var process = new Process
            {
                StartInfo =
                {
                    FileName = "ping", 
                    UseShellExecute = false, 
                    CreateNoWindow = true,
                    RedirectStandardOutput = true, 
                    RedirectStandardError = true,                    

                },
                EnableRaisingEvents = true
            };


            var obs = Observable.FromEventPattern(handler => process.Exited += handler, handler => process.Exited -= handler);

            var started = process.Start();
            if (!started)
            {
                throw new InvalidOperationException("Could not start process: " + process);
            }

            await obs.FirstAsync();
        }
    }
}

能否请您告诉我如何使用IObservable使其工作?

1 个答案:

答案 0 :(得分:1)

您在这里有比赛条件。来自this RX repro thread的引用:

  

FirstAsync返回一个可观察到的寒冷。直到您订阅   还是等待您会收到消息。

TaskCompletionSource(在此使用更合适,IMO)不同,FirstAsync返回的可观察对象并不会“缓存”之前发生的事件。 >您通过等待订阅来激活它。因此,process.Exited事件在await obs.FirstAsync()之前被触发,因此.NET启动代码阻止了Main返回的任务。

以下内容将按预期工作(您需要添加using System.Reactive.Threading.Tasks):

var task = obs.FirstAsync().ToTask();

var started = process.Start();
if (!started)
{
    throw new InvalidOperationException("Could not start process: " + process);
}

await task;

在此之前,我们通过将可观察的订阅转换为Task来激活它。

如果对Observable.FromEventPattern之类的东西感兴趣但对TaskCompletionSource感兴趣,请选中this Q/A