我的应用程序中的主窗体启动一个新线程,然后打开另一个窗体,该窗体用作进度窗口。
该线程在2个控制台应用程序之间传递一些数据,并将来自StandardError的信息发送到进度窗口。我使用DataReceivedEventHandler异步读取standarderror。
如果我让一切顺利进行,则可以正常工作,但是当用户按下表单上的“取消”按钮时,就会出现问题。发生了什么,即使我停止了进程,ErrorDataReceived函数仍会触发!有时取消会成功完成,但有时会出现死锁情况(我认为这是正确的词)。
这是我的代码的一些摘要,因此您可以了解发生了什么。等待“ p2.WaitForExit();”时卡住了和“调用(新的updateProgressDelegate(this.updateProgress),e.Data);”
(Visual Studio在这些线旁边放了一个绿色箭头,并说它们将是下一个执行的箭头)
// start 2 processes (p & p2) and pipe data from one to the other
// this runs in thread t
p.Start();
p2.Start();
byte[] buf = new byte[BUFSIZE];
int read = 0;
p2.ErrorDataReceived += new DataReceivedEventHandler(p2_ErrorDataReceived);
p2.BeginErrorReadLine();
try
{
read = p.StandardOutput.BaseStream.Read(buf, 0, BUFSIZE);
while (read > 0 && read <= BUFSIZE)
{
if (canceled==false)
p2.StandardInput.BaseStream.Write(buf, 0, read);
if (canceled==false)
read = p.StandardOutput.BaseStream.Read(buf, 0, BUFSIZE);
else
{
return;
}
}
}
// this function is called when a user presses the "cancel" button on a form.
private void cancel_encode()
{
if (p2 != null)
{
if (p2.HasExited == false)
p2.Kill();
if (p2.HasExited == false)
p2.WaitForExit();
}
if (p != null)
{
if (p.HasExited == false)
p.Kill();
if (p.HasExited == false)
p.WaitForExit();
}
if (t.IsAlive)
{
if (!t.Join(2000))
t.Abort();
}
}
// this function sends the error data to my progress window
void p2_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null && canceled == false)
Invoke(new updateProgressDelegate(this.updateProgress), e.Data);
}
最佳答案
两件事情
在“ p2_ErrorDataReceived”中,调用Invoke()。这可能导致您陷入僵局。您可能需要将其更改为BeginInvoke()。
Process.WaitForExit()的文档建议,在调用Kill()之后,应调用采用整数的WaitForExit重载,如果返回true,则在不带参数的情况下再次调用它,以确保所有异步处理均已完成:
p2.Kill();
if(p2.WaitForExit(waitTime)) //waitTime is the number of milliseconds to wait
{p2.WaitForExit();} //waits indefinitely
//likewise for p
http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx