asynchronous进程启动并等待它完成

我是.net中的线程模型的新手。 你会用什么来:

  1. 启动一个处理文件的进程(process.StartInfo.FileName = fileName;)
  2. 等待用户closures该进程或在一段时间后放弃该线程
  3. 如果用户closures了进程,请删除该文件

启动进程和等待应该在与主线程不同的线程上完成,因为这个操作不应该影响应用程序。

例:

我的应用程序产生一个HTML报告。 用户可以右键点击某处,然后说“查看报告” – 现在我在一个临时文件中检索报告内容,并启动处理html文件的过程,即默认浏览器。 问题是我无法清理,即删除临时文件。

“等待必须是asynchronous的” – 我不是想要搞笑,但这不是一个矛盾的问题? 但是,由于您正在启动Process ,因此Exited事件可能会有所帮助:

 ProcessStartInfo startInfo = null; Process process = Process.Start(startInfo); process.EnableRaisingEvents = true; process.Exited += delegate {/* clean up*/}; 

如果你想实际等待(超时等),那么:

 if(process.WaitForExit(timeout)) { // user exited } else { // timeout (perhaps process.Kill();) } 

为了等待asynchronous,也许只是使用不同的线程?

 ThreadPool.QueueUserWorkItem(delegate { Process process = Process.Start(startInfo); if(process.WaitForExit(timeout)) { // user exited } else { // timeout } }); 

为这个老问题添加一个高级替代scheme。 如果要等待进程退出而不阻塞任何线程并仍支持超时,请尝试以下操作:

  public static Task<bool> WaitForExitAsync(this Process process, TimeSpan timeout) { ManualResetEvent processWaitObject = new ManualResetEvent(false); processWaitObject.SafeWaitHandle = new SafeWaitHandle(process.Handle, false); TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); RegisteredWaitHandle registeredProcessWaitHandle = null; registeredProcessWaitHandle = ThreadPool.RegisterWaitForSingleObject( processWaitObject, delegate(object state, bool timedOut) { if (!timedOut) { registeredProcessWaitHandle.Unregister(null); } processWaitObject.Dispose(); tcs.SetResult(!timedOut); }, null /* state */, timeout, true /* executeOnlyOnce */); return tcs.Task; } 

同样,与接受的答案相比,这种方法的优点是不会阻塞任何线程,从而降低应用程序的开销。

尝试下面的代码。

 public void KickOffProcess(string filePath) { var proc = Process.Start(filePath); ThreadPool.QueueUserWorkItem(new WaitCallBack(WaitForProc), proc); } private void WaitForProc(object obj) { var proc = (Process)obj; proc.WaitForExit(); // Do the file deletion here } 

我可能不会使用一个单独的过程来打开文件。 相反,我可能会利用后台线程(如果我认为这个操作需要很长时间,可能会阻塞UI线程)。

 private delegate void FileOpenDelegate(string filename); public void OpenFile(string filename) { FileOpenDelegate fileOpenDelegate = OpenFileAsync; AsyncCallback callback = AsyncCompleteMethod; fileOpenDelegate.BeginInvoke(filename, callback, state); } private void OpenFileAsync(string filename) { // file opening code here, and then do whatever with the file } 

当然,这不是一个好的工作示例(它什么都不返回),我没有显示如何更新UI(你必须在UI级别使用BeginInvoke,因为后台线程无法更新UI线程)。 但是这种方法通常是我如何处理.Net中的asynchronous操作。

您可以使用Process类中的Exited事件

 ProcessStartInfo info = new ProcessStartInfo(); info.FileName = "notepad.exe"; Process process = Process.Start(info); process.Exited += new EventHandler(process_Exited); Console.Read(); 

在这种情况下,你可以处理你提到的操作