C# 是否有办法在iSyncumerator中使用System.Diagnostics.Process?

C# 是否有办法在iSyncumerator中使用System.Diagnostics.Process?,c#,process,iasyncenumerable,C#,Process,Iasyncenumerable,首先,我的目标是.NETCore3.1和C#8 我想要这样的东西 public static async Task<MyDataObj> GetData() { var dataObj = new MyDataObj(); var args = ArgsHelperFunction(...); await foreach(string result in RunProcessAsync(args)) { // Process result and st

首先,我的目标是.NETCore3.1和C#8

我想要这样的东西

public static async Task<MyDataObj> GetData()
{
  var dataObj = new MyDataObj();
  var args = ArgsHelperFunction(...);
  
  await foreach(string result in RunProcessAsync(args))
  {
     // Process result and store it in dataObj
  }

  return dataObj;
}

private static async IAsyncEnumerable<string> RunProcessAsync(string args)
{
  await using (var myProcess = new Process())
  {
    myProcess.StartInfo.FileName = @"path\to\file.exe"
    myProcess.StartInfo.Arguments = args;
    myProcess.StartInfo.UseShellExecute = false;
    myProcess.StartInfo.RedirectStandardError = true;
    myProcess.StartInfo.CreateNoWindow = true;

    myProcess.ErrorDataReceived += (s, e) =>
    {
      yield return e.Data;
    }

    myProcess.Start();
    myProcess.BeginErrorReadLine();
    process.WaitforExit();
  }
}
公共静态异步任务GetData() { var dataObj=新的MyDataObj(); var args=argshelfolfuncation(…); 等待foreach(字符串结果为RunProcessAsync(args)) { //处理结果并将其存储在dataObj中 } 返回数据对象; } 专用静态异步IAsyncEnumerable RunProcessAsync(字符串参数) { 等待使用(var myProcess=new Process()) { myProcess.StartInfo.FileName=@“path\to\file.exe” myProcess.StartInfo.Arguments=args; myProcess.StartInfo.UseShellExecute=false; myProcess.StartInfo.RedirectStandardError=true; myProcess.StartInfo.CreateNoWindow=true; myProcess.ErrorDataReceived+=(s,e)=> { 收益率数据; } myProcess.Start(); myProcess.BeginErrorReadLine(); process.WaitforExit(); } } 尝试此设置时,我从
wait-foreach(字符串结果为RunProcessAsync(args))

CS8417“进程”:异步using语句中使用的类型必须隐式转换为“System.IAsyncDisposable”或实现适当的“DisposeAsync”方法

产生的这个错误返回e.数据

CS1621不能在匿名方法或lambda表达式中使用yield语句

目标就是这样。我有一个exe,它做一些事情,并将信息写入错误输出流(不确定这是否是它的真实名称)。我想在写的过程中接受这些内容,解析它们以获得我想要的信息,并将它们存储在一个对象中供以后使用

我是一个相当初级的程序员,对异步编码非常陌生。我以同步方式测试了
RunProcessAsync
的功能;它被调用,只是将所有原始数据写入输出窗口,而不将任何数据返回给调用方法。效果很好。另外,我得到了一个使用
IAsyncEnumerable
的测试asyc流,但它只使用了
Task.Delay
并返回了一些整数。现在我正试图把这些东西结合起来,而我缺乏经验正阻碍着我

感谢你们所有人可能给予的任何帮助,感谢你们帮助提高C#的技能和知识。

没有a,就不可能完全解决你们的问题。但我们可以处理你提出的两个具体问题

首先,如果您的对象(例如
Process
)不支持
IAsyncDisposable
,那么就不要使用它。改用同步
using
语句

至于方法中的
收益率
,如果你花点时间,你可能会发现你试图写的东西没有任何意义。事件处理程序是一个完全不同的方法,它如何使当前方法产生一个新值?您需要事件处理程序在事件发生时向当前方法发送信号。您可以通过多种方式来实现这一点,但是
SemaphoreSlim
是一种更简单的方式

把这些放在一起,你可能会得到如下结果:

私有静态异步IAsyncEnumerable RunProcessAsync(字符串参数)
{
使用(var myProcess=new Process())
{
myProcess.StartInfo.FileName=@“path\to\file.exe”;
myProcess.StartInfo.Arguments=args;
myProcess.StartInfo.UseShellExecute=false;
myProcess.StartInfo.RedirectStandardError=true;
myProcess.StartInfo.CreateNoWindow=true;
ConcurrentQueue dataQueue=新ConcurrentQueue();
SemaphoreSlim dataSemaphore=新的SemaphoreSlim(0);
myProcess.ErrorDataReceived+=(s,e)=>
{
dataQueue.Enqueue(即数据);
dataSemaphore.Release();
}
myProcess.Start();
myProcess.BeginErrorReadLine();
while(true)
{
等待dataSemaphore.WaitAsync();
//只有一个消费者,因此这将始终成功
TryDequeue(输出字符串数据);
如果(数据==null)中断;
收益率数据;
}
}
}
由于您没有提供实际的MCVE,因此我无法尝试从头开始重建您的场景。所以上面的内容没有经过编译,更不用说测试了。但它应该说明要点

也就是说,您需要使迭代器方法保持异步(这意味着您不能阻止调用
WaitForExit()
),并且您需要以某种方式将
ErrorDataReceived
事件处理程序接收的数据移回迭代器方法。在上面,我将线程安全队列对象与信号量结合使用

每次接收到一行数据时,事件处理程序中的信号量计数都会增加(通过
Release()
),然后迭代器方法通过减少信号量计数(通过
WaitAsync()
)并返回接收到的行来使用该数据

这里还有很多其他机制可以用于生产者/消费者方面。这里有一个讨论异步兼容机制的例子,包括支持异步操作的自定义版本的
BlockingCollection
,还有一个来自TPL数据流的例子

下面是一个使用
BufferBlock
的示例(其语义非常类似于
BlockingCollection
,但包括消费代码的异步处理):

静态异步IAsyncEnumerable RunProcessAsync(字符串参数)
{
使用(var进程=新进程())
{
myProcess.StartInfo.FileName=@“path\to\file.exe”;
process.StartInfo.Arguments=args;
process.StartInfo.UseShellExecute=false;
process.StartInfo.RedirectStandardError=true;
process.StartInfo.CreateNoWindow=true;
BufferBlock-dataBuffer=新的BufferBlock();
process.ErrorDataReceived+=(s,e)=>
{
如果(如数据!=null)
{
dataBuffer.Post(e.Data);
}
其他的