C# 等待过程。从可观察开始

C# 等待过程。从可观察开始,c#,.net,async-await,system.reactive,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 M

我创建了以下代码。我原以为它会起作用,但事实并非如此。等待无限期地挂起(从不调用退出事件)

我打电话给“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使其工作

这里有一个比赛条件。引自:

FirstAsync返回一个冷的可观察值。直到你订阅 等待或等待您收到消息

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

以下操作将按预期工作(您需要使用System.Responsive.Threading.Tasks添加
):

在这里,我们通过在启动流程之前将其转换为任务来激活可观察订阅

如果对类似于
可观察的.FromEventPattern
的内容感兴趣,但对于
任务完成源代码
,请检查

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

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

await task;