views:

197

answers:

1

The main form in my application launches a new thread, and then opens another form, which serves as a progress window. The thread pipes some data between 2 console applications, and information from the StandardError is sent to the progress window. I use the DataReceivedEventHandler to read the standarderror asynchronously.

If I let everything run its course, it works perfectly fine, but a problem arises when a user presses the "cancel" button on my form. What happens, is the ErrorDataReceived functions keep firing even after I stop the processes! Sometimes the cancel will work successfully, but sometimes I get a deadlock condition (I think that's the right word).

Here are some snippets of my code so you can see whats happening. It gets stuck waiting on "p2.WaitForExit();" and "Invoke(new updateProgressDelegate(this.updateProgress), e.Data);" (visual studio puts a green arrow by those lines, and says they will be the next to execute)

// 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);
        }
+1  A: 

two things

In "p2_ErrorDataReceived", you call Invoke(). This may be causing part of your deadlock. You may want to change that to BeginInvoke().

The documentation for Process.WaitForExit() suggests that after you call Kill(), you should call the WaitForExit overload that takes an integer, and if it returns true, call it again without a parameter to ensure all the asynchronous processing has completed:

 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

dan
Using BeginInvoke() seems to have fixed it! Thanks.
Zarxrax