In the code below, I want to synchronize reporting on the results of a task list. This now works because task.Result blocks until the task completes. However, the id = 3 task takes a long time to complete and blocks all other completed tasks, reporting its status.
I think I can do this by moving the report (Console.Write) to the .ContinueWith statement, but I don't have a user interface thread, so how can I get TaskScheduler to synchronize .ContinueWith tasks?
What I have now:
static void Main(string[] args) { Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId); var tasks = new List<Task<int>>(); for (var i = 0; i < 10; i++) { var num = i; var t = Task<int>.Factory.StartNew(() => { if (num == 3) { Thread.Sleep(20000); } Thread.Sleep(new Random(num).Next(1000, 5000)); Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId); return num; }); tasks.Add(t); } foreach (var task in tasks) { Console.WriteLine("Completed {0} on {1}", task.Result, Thread.CurrentThread.ManagedThreadId); } Console.WriteLine("End of Main"); Console.ReadKey(); }
I would like to move on to this or something similar, but I need Console.Write ("Completed ...") so that everything happens in the same thread:
static void Main(string[] args) { Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId); for (var i = 0; i < 10; i++) { var num = i; Task<int>.Factory.StartNew(() => { if (num == 3) { Thread.Sleep(20000); } Thread.Sleep(new Random(num).Next(1000, 10000)); Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId); return num; }).ContinueWith(value => { Console.WriteLine("Completed {0} on {1}", value.Result, Thread.CurrentThread.ManagedThreadId); } ); } Console.WriteLine("End of Main"); Console.ReadKey(); }
- SOLUTION - After receiving some comments and reading some solutions, this is a complete solution that does what I want. The goal here is to process long-running tasks as quickly as possible, and then do something with the results of each task one at a time.
static void Main(string[] args) { Console.WriteLine("Starting on {0}", Thread.CurrentThread.ManagedThreadId); var results = new BlockingCollection<int>(); Task.Factory.StartNew(() => { while (!results.IsCompleted) { try { var x = results.Take(); Console.WriteLine("Completed {0} on {1}", x, Thread.CurrentThread.ManagedThreadId); } catch (InvalidOperationException) { } } Console.WriteLine("\r\nNo more items to take."); }); var tasks = new List<Task>(); for (var i = 0; i < 10; i++) { var num = i; var t = Task.Factory.StartNew(() => { if (num == 3) { Thread.Sleep(20000); } Thread.Sleep(new Random(num).Next(1000, 10000)); Console.WriteLine("Done {0} on {1}", num, Thread.CurrentThread.ManagedThreadId); results.Add(num); }); tasks.Add(t); } Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => results.CompleteAdding()); Console.WriteLine("End of Main"); Console.ReadKey(); }