C#只有一个线程执行

时间:2012-05-25 11:04:23

标签: c# multithreading

我有一个多线程应用程序。我希望只有一个线程执行我的函数,而其他线程在执行函数时传递它。我怎么能这样做?

我的方法类似于:

    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);
        }
    }

5 个答案:

答案 0 :(得分:11)

您可以将锁定对象与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);
        }
    }
}

此时只允许一个线程进入Monitor.TryEnter块。如果一个线程到达此处而另一个线程在里面,那么Monitor.TryEnter将返回false

答案 1 :(得分:2)

您可以使用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();
    }
}

答案 2 :(得分:0)

您可以为线程命名并检查方法中的名称

答案 3 :(得分:0)

这个解决方案怎么样:

private AutoResetEvent are = new AutoResetEvent();

public void setOutput(int value)
{
    // Do not wait (block) == wait 0ms
    if(are.WaitOne(0))
    {
        try
        {
            // Put your code here
        }
        finally
        {
            are.Set()
        }
    }
}

使用锁定对象似乎比Monitor更容易(更便宜),但可能不那么清楚。

答案 4 :(得分:0)

公认的答案(撰写时为https://stackoverflow.com/a/10753349/1606741)是正确的,但我认为使用https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement更为清晰,并且基本相同。

一次有一个线程可以执行该块

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);
            }
        }
    }