2017-05-04 159 views
0

我有這樣的C#中止通過cmd.StandardOutput.ReadToEnd()啓動一個外部進程

Process cmd = new Process(); 
cmd.StartInfo.FileName = "cmd.exe"; 
cmd.StartInfo.RedirectStandardInput = true; 
cmd.StartInfo.RedirectStandardOutput = true; 
cmd.StartInfo.RedirectStandardError = true; 
cmd.StartInfo.CreateNoWindow = true; 
cmd.StartInfo.UseShellExecute = false; 
cmd.Start(); 

string fullcmd = "\"" + doorsExe + "\" -osUser -b \"" + "doors_" + genname + ".dxl" + "\""; 

cmd.StandardInput.WriteLine(fullcmd); 
cmd.StandardInput.Flush(); 
cmd.StandardInput.Close(); 
cmd.WaitForExit(); 

string result; 

// HERE I WILL BECOME BLOCKED! 
if ((result = cmd.StandardOutput.ReadToEnd()) != string.Empty) 
    RaiseMessageEvent(result, Color.Gray); 

現在我用這一切

if (!bgwImport.CancellationPending) 
{ 
... 
} 

但當然的BG工人的DoWork() ,不能取消,因爲有一個阻塞所有東西的外部進程。沒關係,因爲UI沒有被封鎖(這就是我使用BGW的原因),但是我實現了一個「取消」按鈕,它不起作用。

如何停止

cmd.StandardOutput.ReadToEnd() 

提前感謝!

+1

切換到異步讀取stderr/stdout可能會解決您的死鎖問題。我已經完成了簡單的版本[這裏](http://stackoverflow.com/a/38491255/5095502),這對我有效。爲了使它像你的代碼一樣工作,只需改變'(sender,args1)=> Console.WriteLine(args1.Data);'將數據附加到某個字符串,然後最後那個字符串將與您期望的相同結果「。 – Quantic

+1

另外請注意,你已經給了我們一個[XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem),我上面的評論是修復你的'實際'死鎖的問題,對你提到的問題的回答是將一個Process對象附加到'doorsExe'和['Kill()'](https://msdn.microsoft.com/en-us/library/system.diagnostics。 process.kill(v = vs.110).aspx)。 – Quantic

+0

考慮在達到大錘解決方案之前修復代碼中的錯誤。當你開始讀取輸出之前,要求進程先退出時,這個程序很可能會死鎖。 –

回答

0

很清楚,sync/async,感謝提示。但是,我已經在後臺工作,所以async並不重要。

終於解決了,萬一有人像我一樣從頭部拉出頭髮。

感謝-1無論如何,非常鼓舞人心!

在任何情況下都會中止,我在TaskManager中檢查過,門的工作很好。但是,我花了一個小時才弄清楚如何捕獲重定向的輸出,但沒有成功。總是返回NULL。我只是放棄了,我只需要取消那個過程。

  String command = "\"" + doorsExe + "\" -osUser -b doors_" + genname + ".dxl"; 
      ProcessStartInfo cmdsi = new ProcessStartInfo("cmd.exe", "/c" + command); 

      cmdsi.CreateNoWindow = true; 
      cmdsi.UseShellExecute = false; 

      Process cmd = new Process(); 
      cmd = Process.Start(cmdsi); 

      while (!cmd.HasExited) 
      { 

       if (bgwImport.CancellationPending) 
       { 
        e.Cancel = true; 
        return; 
       } 

      }