7

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

我的方法是这样的:

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

5 回答 5

12

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

于 2012-05-25T11:07:10.373 回答
2

您可以使用互斥锁

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();
    }
}
于 2012-05-25T11:08:54.983 回答
1

接受的答案(写作时https://stackoverflow.com/a/10753349/1606741 )是正确的,但我认为使用https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/关键字/锁定语句更清晰,并且基本相同。

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

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);
            }
        }
    }
于 2019-09-03T15:43:14.960 回答
0

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

于 2012-05-25T11:14:57.317 回答
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锁定对象更容易(更便宜),但可能不太清楚。

于 2017-10-31T12:36:56.210 回答