I have a Winforms app that lives in the taskbar area. A window opens up for logging output.
Now, in my component (still on UI Thread here) I need to call an external process that runs 5-15min and produces files. I need to wait for the process to exit and consume those files.
Since I want my UI to be responsive (move the Window, etc.) I implemented an agent and am calling the process with BeginInvoke/EndInvoke:
private delegate int BeginCallDelegate( int port, int baud, int timeout, Job job );
private BeginCallDelegate del = null;
public IAsyncResult BeginCall( int port, int baud, int timeout, Job job )
{
del = new BeginCallDelegate( Call );
IAsyncResult iar = del.BeginInvoke( port, baud, timeout, job, null, null );
return iar;
}
In the calling code I am polling the IAsyncResult with WaitOne() but notice that the UI is extremely unresponsive if not frozen:
IAsyncResult a = agent.BeginCall(...); //BeginInvoke
while ( !a.IsCompleted )
{
iar.AsyncWaitHandle.WaitOne( 250 );
//writing something to a textbox works here, but overall responsiveness is weak
}
agent.EndCall( iar ); //EndInvoke
VS tells me the external process is started on a worker thread, but why does that not help with my UI responsiveness? IT should NOT block the calling thread
Here's the code that launches the process:
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "app.exe";
psi.Arguments = String.Format( "blah blah", port, baud, timeout, job.FullName );
psi.CreateNoWindow = false;
psi.ErrorDialog = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo = psi;
if ( !process.Start() )
throw new Exception( "The process cannot start." );
process.WaitForExit( job.Timeout );
Hint: To test, the external app.exe is a dummy app that does nothing else but Thread.Sleep(60000). CPU Load is 3%.
Another question: How would I do this the "TPL way" without using Begin/EndInvoke?