Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async process start and wait for it to finish

I am new to the thread model in .net. What would you use to:

  1. start a process that handles a file (process.StartInfo.FileName = fileName;)
  2. wait for the user to close the process OR abandon the thread after some time
  3. if the user closed the process, delete the file

Starting the process and waiting should be done on a different thread than the main thread, because this operation should not affect the application.

Example:

My application produces an html report. The user can right click somewhere and say "View Report" - now I retrieve the report contents in a temporary file and launch the process that handles html files i.e. the default browser. The problem is that I cannot cleanup, i.e. delete the temp file.

like image 393
Bogdan Gavril MSFT Avatar asked Mar 04 '09 15:03

Bogdan Gavril MSFT


People also ask

How do I wait for async?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

Does process start async?

Indeed, Process. Start is async and the OP appears to want a synchronous version.

How do you call async method without await?

However, just to address "Call an async method in C# without await", you can execute the async method inside a Task. Run . This approach will wait until MyAsyncMethod finish. await asynchronously unwraps the Result of your task, whereas just using Result would block until the task had completed.

Can async method have multiple awaits?

For more information, I have an async / await intro on my blog. So additionally, if a method with multiple awaits is called by a caller, the responsibility for finishing every statement of that method is with the caller.


2 Answers

"and waiting must be async" - I'm not trying to be funny, but isn't that a contradiction in terms? However, since you are starting a Process, the Exited event may help:

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

If you want to actually wait (timeout etc), then:

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

For waiting async, perhaps just use a different thread?

ThreadPool.QueueUserWorkItem(delegate {     Process process = Process.Start(startInfo);     if(process.WaitForExit(timeout)) {         // user exited     } else {         // timeout     } }); 
like image 113
Marc Gravell Avatar answered Sep 22 '22 07:09

Marc Gravell


Adding an advanced alternative to this old question. If you want to wait for a process to exit without blocking any thread and still support timeouts, try the following:

    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;     } 

Again, the advantage to this approach compared to the accepted answer is that you're not blocking any threads, which reduces the overhead of your app.

like image 27
Chris Gillum Avatar answered Sep 20 '22 07:09

Chris Gillum