Sunday, 7 May 2017

Async/Await 02

Now if we look back to our guess the number game we can leverage the async/await keywords to group our participants guess results together and check if any of them got the correct answer, if not then call the function again.


using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace pc.AsyncAwait
{
    class Person
    {
        static Random rnd = new Random(DateTime.Now.Millisecond);
        public string Name { get; set; }
        public int Guess { get; private set; } = -1;
        public Person(string Name)
        {
            this.Name = Name;
        }
        public Person GuessNumber(object UpperLimit)
        {
            Task.WaitAll(Task.Delay(rnd.Next(1000, 2000)));

            Guess = rnd.Next(int.Parse(UpperLimit.ToString()));
            Console.WriteLine($"{Name} guessed {Guess}");
            return this;
        }
    }

    class GuessTheNumber
    {
        public int UpperLimit { get; set; }
        public int TheNumber { get; set; }
        public Person[] Participants { get; set; }
        public GuessTheNumber(int TheNumber, Person[] Participants, int UpperLimit = 100)
        {
            this.TheNumber = TheNumber;
            this.Participants = Participants;
            this.UpperLimit = UpperLimit;
        }
        public async Task<Person[]> Start()
        {
            var winners = new List<Person>();
            int phase = 0;

            while (winners.Count < 1)
            {
                winners = await Task.Run(() =>
                {
                    var result = new List<Person>();

                    Parallel.ForEach(Participants, p => {
                        p.GuessNumber(UpperLimit);
                        if (p.Guess == TheNumber)
                            result.Add(p);
                    });

                    return result;
                });
                Console.WriteLine($"Phase {phase++} complete");
            }
            return winners.ToArray();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var ppl = new Person[] {
            new Person("Pawel"), new Person("Magda"),
            new Person("Marin"), new Person("Trish"),
            new Person("Jakub"), new Person("Kelly"),
            new Person("Tomek"), new Person("Natly") };

            var gtnGame = new GuessTheNumber(7, ppl, 10);
            var winners = gtnGame.Start().Result;

            foreach (var w in winners)
                Console.WriteLine($"{w.Name} Picked right");
        }
    }
}


One thing to note is that the Parallel.ForEach  actually waits for all of it's iterations to finish before moving on.