我有一个位于任务栏区域的 Winforms 应用程序。将打开一个用于记录输出的窗口。
现在,在我的组件中(仍然在 UI 线程上)我需要调用一个运行 5-15 分钟并生成文件的外部进程。我需要等待进程退出并使用这些文件。
因为我希望我的 UI 具有响应性(移动窗口等),所以我实现了一个代理并使用 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;
}
在调用代码中,我使用 WaitOne() 轮询 IAsyncResult 但请注意,如果未冻结,UI 将非常无响应:
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 告诉我外部进程是在工作线程上启动的,但为什么这对我的 UI 响应没有帮助?它不应该阻塞调用线程
这是启动该过程的代码:
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 );
提示:为了测试,外部 app.exe 是一个虚拟应用程序,除了 Thread.Sleep(60000) 之外什么都不做。CPU 负载为 3%。
另一个问题:如果不使用 Begin/EndInvoke,我将如何以“TPL 方式”执行此操作?