写入Process.StandardInput时发生死锁
本文关键字:死锁 Process StandardInput 写入 | 更新日期: 2023-09-27 18:26:33
我正在开发一个应用程序,遇到死锁问题。
我的代码是这样的:
Process p = new Process(); // That using an other application
然后我将向这个进程发送一个.xml文件:
XmlSerializer xs = new XmlSerializer(data.GetType());
using (var ms = new MemoryStream())
{
var sw = new StreamWriter(ms);
XmlWriter xmlwriter = XmlWriter.Create(sw, xmlWriterSettings);
xmlwriter.WriteProcessingInstruction("PipeConfiguratorStyleSheet", processing);
xs.Serialize(xmlwriter, data);
xmlwriter.Flush();
ms.Position = 0;
var sr = new StreamReader(ms);
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
p.StandardInput.WriteLine(line);
Console.WriteLine(line);
p.BeginOutputReadLine();
p.CancelOutputRead();
}
}
因此,实际上我可以将.xml文件的一部分发送到我的进程,但在某个时刻我会遇到死锁。我想我不知道如何正确使用BeginOutputReadLine()
。
首先,为什么不像一样直接使用Process.StandardInput
-属性作为目标
var process = new Process
{
// all your init stuff
};
var xmlSerializer = new XmlSerializer(data.GetType());
var xmlwriter = XmlWriter.Create(process.StandardInput, xmlWriterSettings);
xmlSerializer.Serialize(xmlwriter, data);
否则,msdn条目提供了使用Process.BeginOutputReadLine()
的明确方法,您可以将其重新构造为
var autoResetEvent = new AutoResetEvent(false); // this mutex acts as our bouncer for the reading-part
var process = new Process
{
// all your init stuff
};
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, args) => {
// TODO you could read the content here with args.Data
autoResetEvent.Set();
};
process.Start();
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
{
var xmlSerializer = new XmlSerializer(data.GetType());
var xmlwriter = XmlWriter.Create(streamWriter, xmlWriterSettings);
xmlSerializer.Serialize(xmlwriter, data);
}
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
while (!streamReader.EndOfStream)
{
var line = streamReader.ReadLine();
process.StandardInput.WriteLine(line);
Console.WriteLine(line);
process.BeginOutputReadLine();
autoResetEvent.WaitOne();
}
}
}
// TODO closing the process.StandardInput, exiting process, ...
不管怎样——我知道这应该是一条评论——你等待你的流程写东西有什么具体的原因吗?
StandardOutput流可以同步读取,也可以异步读取。Read、ReadLine和ReadToEnd等方法执行同步读取对进程输出流的操作。这些同步读取直到关联的进程写入其StandardOutput流,或关闭流。相反BeginOutputReadLine在StandardOutput流。此方法启用指定的事件处理程序对于流输出,并立即返回给调用者,调用者可以在流输出指向事件时执行其他工作处理程序。
这意味着,如果您的进程没有写入任何内容(并且您正在等待),那么您将无休止地等待响应。。。
编辑
您还应该像一样向Process.ErrorDataReceived
添加一个处理程序
process.StartInfo.RedirectStandardError = true;
process.ErrorDataReceived += (sender, args) => {
// TODO do something with the response of args.Data
autoResetEvent.Set();
};
和
while (!streamReader.EndOfStream)
{
var line = streamReader.ReadLine();
process.StandardInput.WriteLine(line);
Console.WriteLine(line);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
autoResetEvent.WaitOne();
}
以处理错误情况(无论这可能意味着什么)。