C# 是否有办法在iSyncumerator中使用System.Diagnostics.Process?
首先,我的目标是.NETCore3.1和C#8 我想要这样的东西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
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);
}
其他的