I've got a class, "TestRunner", with a callback for outputting results:
public class TestRunner
{
// ...
public delegate void OutputCallback(string msg);
public OutputCallback Output { get; set; }
// ...
}
In a form, I have a method that writes to a textbox that I set the callback equal to:
void WriteToOutput(string msg)
{
// Version 1
this.textBoxOutput.AppendText(msg);
}
public Form1()
{
// ...
installChecker = new TestRunner();
installChecker.Output = WriteToOutput;
// ...
}
When I run in the debugger, I get an InvalidOperationException because textBoxOutput is being accessed from a thread other than the thread it was created on, as discussed on MSDN and SO.
So I changed the WriteToOutput method as recommended in the above references:
delegate void WriteToOutputCallBack(string msg);
void WriteToOutput(string msg)
{
// Version 2
if (this.textBoxOutput.InvokeRequired)
{
WriteToOutputCallBack d = new WriteToOutputCallBack(WriteToOutput);
this.Invoke(d, new object[] { msg });
}
else
{
this.textBoxOutput.AppendText(msg);
}
}
But this seems to have broken my program. In TestRunner, there's a method that redirects standard output from a process to the Output callback:
Process dir = new Process();
dir.StartInfo.RedirectStandardOutput = true;
dir.OutputDataReceived += (sender, args) => Output(args.Data + Environment.NewLine);
// ...
This appeared to work before I added Invoke to WriteToOutput, but with WriteToOutput Version 2, the program hangs when it handles the OutputDataReceived event.
Did I implement the UI cross-thread fix incorrectly? Any idea why it is hanging?