Let's start with the straw enum and a straws class.
enum Straw { Long, Short }
class Straws
{
    //used to
randomly select index for short straws
    Random rnd = new Random(DateTime.Now.Millisecond);
    //array to hold
short straws
    Straw[] _straws;
    //expose the
number of straws
    public int Length { get { return
_straws.Length; } }
    //a straw
indexer that lets us extract straws
    //and resize
the array removing excess slots
    public Straw this[int Index]
    {
        get {
            var pulledStraws = _straws[Index];
            for (; Index + 1 < _straws.Length; Index++)
                _straws[Index] = _straws[Index
+ 1];
            Array.Resize(ref _straws,
_straws.Length - 1);
            return pulledStraws;
        }
    }
    //Constructor
to build collection of straws, with defined
    //number of
short straws
    public Straws(int
NumOfStraws, int
NumOfShortStraws = 1)
    {
        _straws = new Straw[NumOfStraws];
        while (NumOfShortStraws > 0) {
            var randomIndex = rnd.Next(_straws.Length);
            if (_straws[randomIndex] != Straw.Short) {
                _straws[randomIndex] = Straw.Short;
                NumOfShortStraws--;
            }
        }
    }
} 
The constructor would be a perfect place to do some exception handling, things like
- Passing in negative values
- passing in 0 for number of short straws
- passing in a value for short straws that's greater then the total number of straws
but for brevity I've left such things out.
Next let's take a look at our Person class
class Person
{
    //Used to pick
a random straw to select
    Random rnd = new Random(DateTime.Now.Millisecond);
    //simple
identifier 
    public string Name { get; set; }
    //set to
nullable so that person doesn't start with a straw
    public Straw? straw { get; private set; } = null;
    //method that
selects a random straw
    public void
PullStraw(Straws straws) { straw =
straws[rnd.Next(straws.Length)]; }
    //a nice way to
notify who pulled what type of straw
    public override string
ToString() { return $"{Name} pulled a {straw} straw"; }
}
pretty straight forward, on the contrived side, but you get the idea.
next let's look at our main, first with the WaitEventHandler  usage commented out.
class Program
{
    static void Main(string[] args)
    {
        //define some
people
        var ppl = new Person[] { new Person { Name = "Pawel" }, new Person { Name="Magda" },
        new Person { Name = "Misha" }, new Person { Name="Jakub" },         new Person { Name = "Tomek" }, new Person { Name = "Marin" } };
        //instantiate
our straws to pull
        var straws = new Straws(ppl.Length);
        //define a
place to hold our tasks
        var tasks = new Task[ppl.Length];
        //using (var
ewh = new EventWaitHandle(true, EventResetMode.AutoReset))
        {
            //asyncronously
select straw
            for (int i = 0; i
< ppl.Length; i++)
                tasks[i] = Task.Factory.StartNew(x =>
                {
                    // ewh.WaitOne();
                    ppl[int.Parse(x.ToString())].PullStraw(straws);
                    //   ewh.Set();
                }, i);
            //let all tasks
complete before printing out selections
            Task.WaitAll(tasks);
            foreach (var p in ppl)
                Console.WriteLine(p.ToString());
        }
    }
}
We crated an array to store all of our tasks as we create them to facilitate waiting for tasks to complete before trying to output our results.
if we run our application as is we'll get some bizarre behavior, from multiple short straws, to no short straws, however if we uncomment our EventWaitHanlde code all starts working as expected. 
using (var ewh = new EventWaitHandle(true, EventResetMode.AutoReset))
{
    //asyncronously
select straw
    for (int i = 0; i
< ppl.Length; i++)
        tasks[i] = Task.Factory.StartNew(x =>
        {
            ewh.WaitOne();
            ppl[int.Parse(x.ToString())].PullStraw(straws);
            ewh.Set();
        }, i);
    //let all tasks
complete before printing out selections
    Task.WaitAll(tasks);
    foreach (var p in ppl)
        Console.WriteLine(p.ToString());
}
this works as expected, because of the EventWaitHandle object we created, because we initialize it to true, this means the first time a thread hits the ewh.WaitOne() method call it continues on but blocks all other tasks at that point because we set the Event reset mode to auto, marking the handler as not signaled every time we "Use" a signal; after our person picks their straw we mark the handler as "Signaled" to let another task have a go, and so on. Once all the tasks complete, then our Tasks.WaitAll(tasks) line lets our main thread continue. 
so now that we've leveraged EventWaitHandle handler, let's drop this whole keeping track of tasks and waiting for them by leveraging the CountDownEvent.
class Program
{
    static void Main(string[] args)
    {
        //define some
people
        var ppl = new Person[] { new Person { Name = "Pawel" },
            new Person { Name="Magda" }, new Person { Name = "Misha" },
            new Person { Name="Jakub" }, new Person { Name = "Tomek" },
            new Person { Name = "Marin" } };
        //instantiate
our straws to pull
        var straws = new Straws(ppl.Length, 2);
        using (var cdh = new CountdownEvent(ppl.Length))
        {
            using (var ewh = new EventWaitHandle(true, EventResetMode.AutoReset))
            {
                //asyncronously
select straw
                foreach (var person in ppl)
                    Task.Factory.StartNew(p =>
                    {
                        ewh.WaitOne();
                        ((Person)p).PullStraw(straws);
                        ewh.Set();
                        cdh.Signal();
                    }, person);
                cdh.Wait();
           
}
            foreach (var p in ppl)
                Console.WriteLine(p.ToString());
        }
    }
}
by using signalling we now have our threads notifying each other of when it's safe to pull a straw and we removed the need to keep track of our tasks by signalling the CountdownEvent of when it's ok to display our results.
