Using WaitAll in C #

7

I have the following problem:

A program generates two types of threads A and B through clicks on their respective buttons. Both types can not run at the same time. If I have 10 threads A, B can only execute when 10 of type A ends.

I can restrict the input by creating a mutex for each type and a Boolean variable that tells me whether there are threads of the other type being executed. However, when the first thread ends, the counter type can enter the critical thread because I am using Mutex.WaitOne ().

How can I adapt the use of 'WaitAll' for this situation? I could not fully understand the concept.

    
asked by anonymous 15.12.2014 / 01:08

1 answer

6

You can resolve this problem by using:

  • a Mutex ( lock )
  • two counters, one for A and one for B
  • and two manual reset events ManualResetEventSlim

    The ManualResetEventSlim is used to stop execution when it reaches the Wait method, but only if it is in não-setado state (there are two states, setado > and não-setado ). Threads can call the Set method to put the object in the setado state, or Reset state to put in não-setado state.

  • example: an easy implementation would be as below. This code however does not handle cases and starvation , which is when As or Bs can be prevented from running if the opposite type of thread comes in more often than the processor is able to execute them. .. so the number of threads of the opposite type only increases.

    private static int a = 0;
    private static int b = 0;
    private static readonly object locker = new object();
    private static readonly ManualResetEventSlim mreA = new ManualResetEventSlim(true);
    private static readonly ManualResetEventSlim mreB = new ManualResetEventSlim(true);
    
    static void A()
    {
        while (true)
        {
            lock (locker)
            {
                // se não tem Bs executando, então o A pode executar
                if (b == 0)
                {
                    // o A vai executar, então devemos:
                    //  - impedir o acesso de Bs
                    //  - incrementar o contador de As
                    mreB.Reset();
                    a++;
                    break;
                }
            }
    
            // já tem Bs executando, vamos ficar esperando um sinal para continuar A
            mreA.Wait();
        }
    
        Console.WriteLine("A está executando");
    
        lock (locker)
        {
            // o A terminou, então:
            //  - decrementamos o contador de As
            //  - liberamos os Bs, se não houver mais As executando
            a--;
            if (a == 0)
                mreB.Set();
        }
    }
    
    static void B()
    {
        while (true)
        {
            lock (locker)
            {
                // se não tem As executando, então o B pode executar
                if (a == 0)
                {
                    // o B vai executar, então devemos:
                    //  - impedir o acesso de As
                    //  - incrementar o contador de Bs
                    mreA.Reset();
                    b++;
                    break;
                }
            }
    
            // já tem As executando, vamos ficar esperando um sinal para continuar B
            mreB.Wait();
        }
    
        Console.WriteLine("B está executando");
    
        lock (locker)
        {
            // o B terminou, então:
            //  - decrementamos o contador de Bs
            //  - liberamos os As, se não houver mais Bs executando
            b--;
            if (b == 0)
                mreA.Set();
        }
    }
    

Previous answer

ReaderWriterLockSlim

What are A and B? It seems to me the case of a reader-writer lock , where reading can be performed several times at the same time, and writing can only be executed if nothing else is running, neither writing nor reading being done.

If this is the case, it is best to use a ReaderWriterLockSlim , which is part of the .Net framework, which serves exactly that.

    
15.12.2014 / 07:13