ManualResetEvent endEventErr = new ManualResetEvent (false);
ManualResetEvent endEventExit = new ManualResetEvent (false);
bool done;
+ bool disposed;
object lockObj = new object ();
public ProcessWrapper ()
base.EnableRaisingEvents = true;
base.Exited += (s, args) => {
- endEventExit.Set ();
+ try {
+ endEventExit.Set ();
+ WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr });
+ } catch (ObjectDisposedException) {
+ return; // we already called Dispose
+ }
- WaitHandle.WaitAll (new WaitHandle[] { endEventOut, endEventErr });
OnExited (this, EventArgs.Empty);
};
base.OutputDataReceived += (s, args) => {
if (args.Data == null) {
- endEventOut.Set ();
+ try {
+ endEventOut.Set ();
+ } catch (ObjectDisposedException) {
+ return; // we already called Dispose
+ }
} else {
ProcessEventHandler handler = OutputStreamChanged;
if (handler != null)
- handler (this, args.Data);
+ handler (this, args.Data + Environment.NewLine);
}
};
base.ErrorDataReceived += (s, args) => {
if (args.Data == null) {
- endEventErr.Set ();
+ try {
+ endEventErr.Set ();
+ } catch (ObjectDisposedException) {
+ return; // we already called Dispose
+ }
} else {
ProcessEventHandler handler = ErrorStreamChanged;
if (handler != null)
- handler (this, args.Data);
+ handler (this, args.Data + Environment.NewLine);
}
};
protected override void Dispose (bool disposing)
{
- lock (lockObj) {
- if (endEventOut == null)
- return;
- }
+ if (disposed)
+ return;
if (!done)
((IAsyncOperation)this).Cancel ();
+ // if we race with base.Exited, we don't want to hang on WaitAll (endEventOut, endEventErr)
+ endEventOut.Set ();
+ endEventErr.Set ();
+
endEventOut.Close ();
endEventErr.Close ();
endEventExit.Close ();
+ disposed = true;
+
base.Dispose (disposing);
}
void CheckDisposed ()
{
- if (endEventOut == null)
+ if (disposed)
throw new ObjectDisposedException ("ProcessWrapper");
}