【发布时间】:2019-01-02 01:37:25
【问题描述】:
我在 C# 中有这个任务应该返回 DISM 的标准输出,所以我可以在需要的地方使用它:
public async Task<StreamReader> DISM(string Args)
{
StreamReader DISMstdout = null;
await Task.Run(() =>
{
Process DISMcmd = new Process();
if (Environment.Is64BitOperatingSystem)
{
DISMcmd.StartInfo.FileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "SysWOW64", "dism.exe");
}
else
{
DISMcmd.StartInfo.FileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "System32", "dism.exe");
}
DISMcmd.StartInfo.Verb = "runas";
DISMcmd.StartInfo.Arguments = DISMArguments;
DISMcmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
DISMcmd.StartInfo.CreateNoWindow = true;
DISMcmd.StartInfo.UseShellExecute = false;
DISMcmd.StartInfo.RedirectStandardOutput = true;
DISMcmd.EnableRaisingEvents = true;
DISMcmd.Start();
DISMstdout = DISMcmd.StandardOutput;
DISMcmd.WaitForExit();
});
return DISMstdout;
}
但这并没有真正起作用。 如果我想读取另一个任务的标准输出,我不能(因为它是空的)所以我的任务一定有问题?
public async Task Test()
{
await Task.Run(() =>
{
StreamReader DISM = await new DISM("/Get-ImageInfo /ImageFile:" + ImagePath + @" /Index:1");
string data = string.Empty;
MessageBox.Show(DISM.ReadToEnd()); // this should display a msgbox with the standardoutput of dism
while ((data = DISM.ReadLine()) != null)
{
if (data.Contains("Version : "))
{
// do something
}
}
});
}
这段代码有什么问题?
【问题讨论】:
-
您在进程退出后返回进程的标准输出流,此时进程不再存在,我猜它的标准 IO 流也不存在 - .NET 必须保留它们直到为您朗读为止。
-
在调用
WaitForExit()之前尝试从流中读取数据,我敢打赌你的数据会在那里。我会做一些事情,比如将回调传递给从流中读取的DISM(),并将回调的结果作为方法的返回值返回。然后,一旦您通过await DISM(...),整个 shebang 就会执行 -
最后但同样重要的是,我不希望
ReadLine()在您调用ReadToEnd()后返回任何内容。ReadToEnd()并不意味着“读取所有当前可用的数据”,它意味着“阻塞直到流关闭并且不再有数据可用” -
在您读取程序的所有输出之前,程序无法退出。所以 WaitForExit() 很可能会死锁。目前尚不清楚为什么需要它,但如果需要,请考虑 Exited 事件。请改用 StringReader。
-
尝试将调用方式改为:
StreamReader DISMoutput = await this.DISM("(...)");。 (没有new)完全消除Task.Run() lambda。在另一种方法中,消除DISMcmd.EnableRaisingEvents = true;。应该去异步。并检查您传递的参数。
标签: c# async-await task