Small sample program never exits
tscode111 opened this issue · 2 comments
Thomas,
Per our messaging. We wrote a simple console app utilizing ObjectDumper to view an object.
The program never returns in ANY instance when using ObjectDumper.Dump - whether the dummy persons object is being dumped only or the eggTask.
Thanks for any insight.
T.
Here is the sample:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Timers;
namespace AsyncBreakfast
{
class Egg { }
class Bacon { }
class Juice { }
class Toast { }
class Coffee { }
public class Person
{
// Auto-implemented properties.
public int Age { get; set; }
public string Name { get; set; }
public Person()
{
}
public Person(string name)
{
this.Name = name;
}
}
class Program
{
static async Task Main(string[] args)
{
Coffee cup = PourCoffee();
Console.WriteLine("coffee is ready");
var eggsTask = FryEggsAsync(2);
var baconTask = FryBaconAsync(3);
var toastTask = MakeToastWithButterAndJamAsync(2);
/*
List<Person> persons = new List<Person>
{
new Person () { Name = "John", Age = 20, },
new Person () { Name = "Thomas", Age = 30, },
};
var personsDump = ObjectDumper.Dump(persons);
Console.WriteLine(personsDump);
Console.ReadLine();
var dumper = ObjectDumper.Dump(eggsTask);
Console.WriteLine(dumper);
Console.ReadLine();
*/
Console.WriteLine("Going in to while() loop");
var breakfastTasks = new List<Task> { eggsTask, baconTask, toastTask };
while (breakfastTasks.Count > 0)
{
Console.WriteLine("In while() loop");
Task finishedTask = await Task.WhenAny(breakfastTasks);
Console.WriteLine("Obj returned ------> {0}", finishedTask.ToString());
if (finishedTask == eggsTask)
{
Console.WriteLine("eggs are ready");
}
else if (finishedTask == baconTask)
{
Console.WriteLine("bacon is ready");
}
else if (finishedTask == toastTask)
{
Console.WriteLine("toast is ready");
}
breakfastTasks.Remove(finishedTask);
}
Juice oj = PourOJ();
Console.WriteLine("oj is ready");
Console.WriteLine("Breakfast is ready!");
/*
var dumper = ObjectDumper.Dump(eggsTask);
Console.WriteLine(dumper);
Console.ReadLine();
*/
}
static async Task<Toast> MakeToastWithButterAndJamAsync(int number)
{
var toast = await ToastBreadAsync(number);
ApplyButter(toast);
ApplyJam(toast);
return toast;
}
private static Juice PourOJ()
{
Console.WriteLine("Pouring orange juice");
return new Juice();
}
private static void ApplyJam(Toast toast) =>
Console.WriteLine("Putting jam on the toast");
private static void ApplyButter(Toast toast) =>
Console.WriteLine("Putting butter on the toast");
private static async Task<Toast> ToastBreadAsync(int slices)
{
for (int slice = 0; slice < slices; slice++)
{
Console.WriteLine("Putting a slice of bread in the toaster");
}
Console.WriteLine("Start toasting...");
Console.WriteLine("Toast 1 {0:HH:mm:ss.fff}", DateTime.Now);
await Task.Delay(3000);
Console.WriteLine("Toast 2 {0:HH:mm:ss.fff}", DateTime.Now);
Console.WriteLine("Remove toast from toaster");
return new Toast();
}
private static async Task<Bacon> FryBaconAsync(int slices)
{
Console.WriteLine($"putting {slices} slices of bacon in the pan");
for (int slice = 0; slice < slices; slice++)
{
Console.WriteLine($"flipping {slice} slice of bacon");
Console.WriteLine("Bacon 1 {0:HH:mm:ss.fff}", DateTime.Now);
await Task.Delay(3000);
Console.WriteLine("Bacon 2 {0:HH:mm:ss.fff}", DateTime.Now);
}
Console.WriteLine("Put bacon on plate");
return new Bacon();
}
private static async Task<Egg> FryEggsAsync(int howMany)
{
Console.WriteLine("Warming the egg pan...");
Console.WriteLine("Egg 1 {0:HH:mm:ss.fff}", DateTime.Now);
await Task.Delay(3000);
Console.WriteLine("Egg 2 {0:HH:mm:ss.fff}", DateTime.Now);
Console.WriteLine($"cracking {howMany} eggs");
Console.WriteLine("cooking the eggs ...");
Console.WriteLine("Egg 3 {0:HH:mm:ss.fff}", DateTime.Now);
await Task.Delay(3000);
Console.WriteLine("Egg 4 {0:HH:mm:ss.fff}", DateTime.Now);
Console.WriteLine("Put eggs on plate");
return new Egg();
}
private static Coffee PourCoffee()
{
Console.WriteLine("Pouring coffee");
return new Coffee();
}
}
}
The program works as expected. I think there is just too many things going on to understand why the program seems to hang in one part. Let me analyze what you're doing:
- ObjectDumper.Dump(eggsTask) --> you're attempting to serialize the Task instance and write it to console output. Of course, you can do this, but Task is rather a complex object which can change its state while executing. So, you'll just so a snapshot of the very moment.
- Console.Readline blocks the execution from proceeding. I think that's what "hangs" your program. When you remove all Console.Readline calls, all the dumps are written to console as expected.
- The while loop around breakfastTasks is very dangerous: You're using a non-thread-safe collection (
List<T>
) to perform asynchronous operations on it (breakfastTasks.Remove(finishedTask)
). Instead, you'd better use Task.WhenAll to await the completion of all asynchronously run tasks.
I get following console output when I run the program. (I had to press 'ENTER' about 2-3x):
console output.txt