Reputation: 570
I have been using System.Threading.Tasks.Task.Run() all over the place with great success. I discovered recently that one of my processes exits prematurely because a Task does not complete. Apparently, I haven't the first clue how System.Threading.Tasks.Task.Run() actually works and my 100,000+ lines of C# code (three windows services, web application, database and in-memory inter-process cache) works by sheer luck. Here is a simplified version of the code. Why does the process exit without executing the delay?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskWaitDemo
{
class Program
{
static void Main(string[] args)
{
Task.Run(() =>
{
while (true)
{
try
{
Task.Delay(60 * 1000).Wait();
// In my actual code I perform real computation right here after the wait.
Console.WriteLine("why does this line never execute???");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
});
}
}
}
EDIT
Trying to embrace the Thread-agnostic world of Tasks, I am using Tasks to two primary purposes: 1) to queue up work to the thread pool, and 2) to handle periodic tasks asynchronously. My example above was an overly simplified attempt to show an example of a periodic task. IN my real application the While (true) { ... }
is actually more like a while (!_shutdown) { ... }
.
The various comments and answers all suggest simply Waiting on the Task, but in my real application the main Thread may or may not have things to do after starting a Task and cannot simply Wait on my periodic Tasks without blocking forever.
In the olden days of Threads, Thread A would start Thread B, and then might gracefully exit if it had nothing left to do, leaving Thread B merrily doing its thing and the process still running.
It seems that, in the brave new world of Tasks, Thread A runs Task B (to queue up some work, possibly periodic, to the thread pool), and then might gracefully exit if it has nothing left to do. The framework then tosses Task B (and apparently any other work queued to the thread pool via Tasks) into the bit bucket and the process terminates. Seems broken to me.
I guess my answer is to use good old Threads for periodic tasks, and hope and pray that all my fire-and-forget Tasks on the thread pool queue are complete before allowing the application to shutdown.
Upvotes: 1
Views: 574
Reputation: 62265
you run while(true)
, yes that is correct, but you run that on another thread.
Main thread, instead, runs all through the Main
and exits the app.
static void Main(string[] args)
{
//MAIN THREAD BOUNDS
//LAUNCH THE TASK AND GO AHEAD
var task = Task.Run(() => (EDIT)
{
//SECOND THREAD BOUNDS
while (true)
{
...
}
//--------------
});
task.Wait(); (EDIT) //WAIT FOR TASK COMPLETION !!!!
//NOTHING MORE TO DO, SO EXIT APP AND KILL Task.Run THREAD
}
EDIT
if you need to wait for the completion just use Task.Wait, like in edited code. In this concrete example it makes no sence, which does not necessary mean it will not in yours.
Upvotes: 4
Reputation: 301
A better structure for your task would be:
static void Main(string[] args)
{
var task = new Task(() =>
{
while (true)
{
Console.WriteLine("Computing..");
Thread.Sleep(1000);
}
});
task.Start();
task.Wait(); //Wait for the task to finish
}
Upvotes: 0