I have a WinForms application that consists of a main UI thread and 4 tasks. My main form has a private member level variable like this:
private bool keepThreadsRunning = false;
In the Load() event of my main form, I have the following:
keepThreadsRunning = true;
var task1Worker = Task.Factory.StartNew(() => DoStuff1());
var task2Worker = Task.Factory.StartNew(() => DoStuff2());
var task3Worker = Task.Factory.StartNew(() => DoStuff3());
var task4Worker = Task.Factory.StartNew(() => DoStuff4());
Inside of each of my DoStuff() methods, I basically have this:
while (keepThreadsRunning)
{
// do work here
Thread.Sleep(30000); // a couple of my tasks only need to run every 30 seconds or so
}
Lastly, in my Form_Closing() event handler, I have the following:
keepThreadsRunning = false;
this.Close();
Watching my application in task manager, it appears that the process is ending when I close my form but I’m a little confused about the four tasks. Is my call to this.Close() really causing those tasks to terminate (even if they’re in the Thread.Sleep() call when it happens)? And is there a better way of accomplishing this than the way I’m coding it right now?
EDIT – I’ve looked briefly at task cancellation (when my app exits) but my understanding is that my tasks would need to periodically check the cancellation token to determine if they’ve been cancelled. Given that some of my tasks need to run every 30 seconds, I couldn’t figure out how I’d implement that 30s wait (currently a Thread.Sleep()) and still have the task be checking the cancellation token.
First of all, closing the main UI thread will terminate your other tasks. If you need them to keep running, maybe consider running them in a seperate Console Application, or a Windows Service.
Even if you found a way to delay the closing of the form while you finish running the methods you need to run, this would only work if the end user closed the form in the way you wanted, and Windows being Windows there are a million and one ways to close an application so there is no guarantee that this will work.
For running a method asynchronously every x amount of seconds, you could just use a timer for the whole thing, like so: