Zakleszczenie - ManualResetEvent

0

Witam, ćwiczę sobie programowanie równoległe i napotkałem takie zadanie:
Korzystając z ManualResetEventSlim, przygotuj program, w którym dwa wątki przekazują sobie "pałeczkę" uprawniającą je do działania. Przy uruchomieniu aplikacji włączy się pierwszy wątek; drugi czeka. Po sekundzie pierwszy wątek wstrzymuje działanie i daje kontrole drugiemu wątkowi. Po kolejnej sekundzie drugi wątek wstrzymuje działanie i daje sygnał do działania pierwszemu wątkowi. I tak aż do momentu, w którym użytkownik zakończy program.

Wszystko pięknie działa jak dodam thread.Sleep(1000) przed Console.WriteLine. Problem mam natomiast jak usunę Thread.Sleep. Pojawia się zakleszczenie i program losowo po "n" rundzie przestaje działać. Jakieś pomysły ?

using System;
using System.Threading;

namespace ManualResetEventSlimExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            ManualResetEvent threadOneController = new ManualResetEvent(true);
            ManualResetEvent threadTwoController = new ManualResetEvent(false);

            ThreadStart action1 = new ThreadStart(() =>
            {
                while (true)
                {
                    threadOneController.WaitOne();
                    Thread.Sleep(0);
                    Console.WriteLine("{0} --- Thread 1 is doing some actions", DateTime.Now);
                    threadTwoController.Set();
                    threadTwoController.Reset();
                    threadOneController.Reset();
                }
            });

            ThreadStart action2 = new ThreadStart(() =>
            {
                while (true)
                {
                    threadTwoController.WaitOne();
                    Thread.Sleep(0);
                    Console.WriteLine("{0} --- Thread 2 is doing some actions", DateTime.Now);
                    threadOneController.Set();
                    threadOneController.Reset();
                    threadTwoController.Reset();
                }
            });

            var t1 = new Thread(action1);
            var t2 = new Thread(action2);

            t1.Start();
            t2.Start();
        }
    }
}
0

Moim zdaniem chodzi tu o to, że gdy nie ma żadnego oczekiwania i operacji zajmującej czas to...
Thread1 - robi Set, drugi wątek "startuje".
Thread2 - w tym samym czasie po starcie (WaitOne) robi się Set na 1 i Resety wykonują się w tym samym czasie gdy jeszcze tam wykonuje się własnie kod na etapie Resetów
Nie przewidzisz w którym momencie wykona się równocześnie, więc moim zdaniem o to chodzi, że nierówno wykona się kod i nawzajem się zblokują dzięki Resetom wywołanym nawzajem siebie.

1

Chyba namieszałeś sobie z tymi resetami i kolejnością:

public static void Main(string[] args)
{
   ManualResetEvent threadOneController = new ManualResetEvent(true);
   ManualResetEvent threadTwoController = new ManualResetEvent(false);

   ThreadStart action1 = () =>
   {
      while (true)
      {
         threadOneController.WaitOne();
         //Thread.Sleep(1000);
         Console.WriteLine("{0} --- Thread 1 is doing some actions", DateTime.Now);
         threadOneController.Reset();
         threadTwoController.Set();
      }
   };

   ThreadStart action2 = () =>
   {
      while (true)
      {
         threadTwoController.WaitOne();
         //Thread.Sleep(1000);
         Console.WriteLine("{0} --- Thread 2 is doing some actions", DateTime.Now);
         threadTwoController.Reset();
         threadOneController.Set();
      }
   };

   var t1 = new Thread(action1);
   var t2 = new Thread(action2);

   t1.Start();
   t2.Start();
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1