4

I have a C# Windows Forms app that launches other processes. When the form closes, I need to shutdown those processes and make sure they're gone so that they don't hang around as zombie processes. My strategy is that I send the processes a shutdown command over a socket bridge, and wait for them to close gracefully. After 3 seconds however, if they are still around, I force close them (kill them).

Originally I used an await Task.Delay(3000) instruction that lived in the Form's Closing event. However that didn't work. By the time the await Task.Delay(3000) statement tried to return, the main thread was already gone so the code after that statement that force closes the child processes if they're still around never executed. To solve the problem I changed await Task.Delay(3000) to a plain Thread.Sleep(3000) statement. Now the code following the Thread.Sleep(3000) executes since the thread is never switched away from as before.

However, that's 3 seconds where my app appears to be unresponsive. What technique could I use instead to make sure the code after the 3 second wait definitely executes, without blocking the main UI thread?

Robert Oschler
  • 14,153
  • 18
  • 94
  • 227
  • I actually don't think this was a duplicate, because what OP is trying to acomplish in the FormClosing is different, therefore, he has different options he can consider. – sstan Jun 18 '15 at 23:16
  • They both are calling async methods inside `FormClosing` – Yuval Itzchakov Jun 18 '15 at 23:19
  • If you have access to the child threads as tasks , you can do the following in your main thread Task.WaitAll(tasks,3000); //tasks are your child threads With WaitAll even you can use CancellationToken to cancel your thread – Dan Hunex Jun 18 '15 at 23:21
  • 1
    @Yuval: The difference is that in this case, he's not trying to prevent the form from closing like in the other question you linked. That changes the potential answers to his question. – sstan Jun 18 '15 at 23:22
  • @sstan Yes, he is: *I need to shutdown those processes and **make sure they're gone**.* If he wants the code to execute, he needs to keep the process alive. – Yuval Itzchakov Jun 18 '15 at 23:23
  • 1
    @Yuval: The fact that the form closes doesn't automatically mean that the process will shutdown. As long as there is still a foreground thread running, which there is if I start one in FormClosing, then the process remains alive. Forgive me if I am the one who is missing the obvious. – sstan Jun 18 '15 at 23:34
  • @Robert Oschler, also related: http://stackoverflow.com/q/20876645/1768303 – noseratio Jun 22 '15 at 20:19

1 Answers1

-4

In the Form's Closing event, you could start a new thread that all it does is:

  • sleep for 3 seconds
  • then kills the processes

Because the sleep occurs on that separate thread, you don't have to worry about freezing the UI. And because your thread is not a background thread, it won't go away while it sleeps :)

EDIT:

I ran this simple test to prove my point. Even after I close the form, and FormClosing event completes, my thread is still running, and the application only truly shuts down after the thread wakes up and finishes its work. Am I crazy?

  private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  {
     Thread t = new Thread(() =>
     {
        Thread.Sleep(10000);
        Debug.WriteLine("I am still alive!!!  So I can still kill the processes here");
        // After this point, the process shuts down, because this was the last thread running.
     });
     t.Start();

     // at this point, the form will close, but the process is still alive as long as thread `t` is alive.
  }

EDIT 2:

To whomever feels the urge to downvote this: at least take my little snippet of code and try it before assuming it won't work. If it completely fails, then downvote me and let me know about it so that I can learn from it.

But as it stands, at least I did my part: I actually tested this, and it does work.

sstan
  • 35,425
  • 6
  • 48
  • 66
  • He already did that but he does not want his main app to freeze – Dan Hunex Jun 18 '15 at 23:18
  • @Dan Hunex: No he didn't. He performed the sleep in the UI thread. I'm suggesting he does the sleep on a separate thread. – sstan Jun 18 '15 at 23:18
  • This will have no effect unless the created thread is `Foreground`. – Yuval Itzchakov Jun 18 '15 at 23:21
  • 2
    If you have access to the child threads as tasks , you can do the following in your main thread Task.WaitAll(tasks,3000); //tasks are your child threads With WaitAll even you can use CancellationToken to cancel your thread – Dan Hunex Jun 18 '15 at 23:26
  • @Yuval: I performed a simple test that you can see in my edit. What is wrong with my example? – sstan Jun 18 '15 at 23:29