Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Only One Thread Executes

I have a multithread application. I want only one thread to execute my function and other threads to pass it while my function executing. How can I do this?

My method is something like:

    public void setOutput(int value)
    {
        try
        {
            GPOs gpos = reader.Config.GPO;
            gpos[1].PortState = GPOs.GPO_PORT_STATE.TRUE;
            gpos[2].PortState = GPOs.GPO_PORT_STATE.TRUE;
            Thread.Sleep(WAIT);
            gpos[1].PortState = GPOs.GPO_PORT_STATE.FALSE;
            gpos[2].PortState = GPOs.GPO_PORT_STATE.FALSE;
        }
        catch (Exception ex)
        {
            logger.Error("An Exception occure while setting GPO to " + value + " " + ex.Message);
        }
    }
like image 989
bhdrkn Avatar asked May 25 '12 11:05

bhdrkn


3 Answers

You can use a lock object in combination with Monitor.TryEnter.

private Object outputLock = new Object();

public void setOutput(int value)
{
    if Monitor.TryEnter(outputLock)
    {
        try
        {
            .... your code in here
        }
        finally
        {
            Monitor.Exit(outputLock);
        }
    }
}

Only one thread at at time will be allowed into the Monitor.TryEnter block. If a thread arrives here while another thread is inside, then Monitor.TryEnter returns false.

like image 154
David Heffernan Avatar answered Sep 20 '22 08:09

David Heffernan


You can use a Mutex

using System;
using System.Threading;

class Test
{
    // Create a new Mutex. The creating thread does not own the
    // Mutex.
    private static Mutex mut = new Mutex();
    private const int numIterations = 1;
    private const int numThreads = 3;

    static void Main()
    {
        // Create the threads that will use the protected resource.
        for(int i = 0; i < numThreads; i++)
        {
            Thread myThread = new Thread(new ThreadStart(MyThreadProc));
            myThread.Name = String.Format("Thread{0}", i + 1);
            myThread.Start();
        }

        // The main thread exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void MyThreadProc()
    {
        for(int i = 0; i < numIterations; i++)
        {
            UseResource();
        }
    }

    // This method represents a resource that must be synchronized
    // so that only one thread at a time can enter.
    private static void UseResource()
    {
        // Wait until it is safe to enter.
        mut.WaitOne();

        Console.WriteLine("{0} has entered the protected area", 
            Thread.CurrentThread.Name);

        // Place code to access non-reentrant resources here.

        // Simulate some work.
        Thread.Sleep(500);

        Console.WriteLine("{0} is leaving the protected area\r\n", 
            Thread.CurrentThread.Name);

        // Release the Mutex.
        mut.ReleaseMutex();
    }
}
like image 42
MrWuf Avatar answered Sep 24 '22 08:09

MrWuf


the accepted answer (https://stackoverflow.com/a/10753349/1606741 as of writing) is right, but I think using https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement is clearer and does basically the same.

One thread at a time can execute the block

private object once = new object();

public void setOutput(int value)
    {
        lock (once)
        {
            try
            {
                GPOs gpos = reader.Config.GPO;
                gpos[1].PortState = GPOs.GPO_PORT_STATE.TRUE;
                gpos[2].PortState = GPOs.GPO_PORT_STATE.TRUE;
                Thread.Sleep(WAIT);
                gpos[1].PortState = GPOs.GPO_PORT_STATE.FALSE;
                gpos[2].PortState = GPOs.GPO_PORT_STATE.FALSE;
            }
            catch (Exception ex)
            {
                logger.Error("An Exception occure while setting GPO to " + value + " " + ex.Message);
            }
        }
    }
like image 24
Garonenur Avatar answered Sep 23 '22 08:09

Garonenur