I'm quite new to threading primitives in C# and was hoping you might be able to suggest improvements to this. I need to ensure that the XXX call below happens within the calling thread (XXX is a foreign call into a thread-unsafe library), so I used a queue here. It seems a bit like there should be a better primitive for this. Maybe delegates are applicable somehow? I don't understand delegates.
I also have to wonder if I've gotten this whole scheme right in the first place! Maybe there's a deadlock I'm not seeing. Threading is so tricky.
As an additional restriction, it's very important that this works on .NET 3.5.
public void RunProc(AutoResetEvent killSubProc)
{
using (Process process = new Process())
{
var timeout = 8000;
var channel = new Queue<string> {};
process.StartInfo.FileName = "blah.exe";
process.StartInfo.Arguments = @"stuff";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.EnableRaisingEvents = true;
using (AutoResetEvent channelWaitHandle = new AutoResetEvent(false))
{
process.OutputDataReceived += (sender, e) => {
if (e.Data != null)
{
lock (channel) { channel.Enqueue("STDOUT"); channel.Enqueue(e.Data); }
channelWaitHandle.Set();
}
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data != null)
{
lock (channel) { channel.Enqueue("STDERR"); channel.Enqueue(e.Data); }
channelWaitHandle.Set();
}
};
process.Exited += (sender, e) =>
{
lock (channel) { channel.Enqueue("EXIT"); }
channelWaitHandle.Set();
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
bool running = true;
while (running)
{
int idx = WaitHandle.WaitAny(new WaitHandle[] {killSubProc, channelWaitHandle});
if (idx == 0)
{
process.Kill();
running = false;
}
else
{
lock (channel)
{
while (channel.Count > 0)
{
var item = channel.Dequeue();
XXX(item);
if (item == "EXIT")
{
running = false;
}
}
}
}
}
}
}
}