thomasgalliker/ObjectDumper

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