我如何才能确保只有一个线程会做什么?只有一个、线程、会做

2023-09-03 15:57:26 作者:〖向日葵〗

我有一个项目添加到一个无锁队列多个线程。 的项目,然后由另外一个线程处理。

I have multiple threads which add items to a lock-free queue. The items are then processed by another thread.

在生产者线程,我要揭开序幕消费者线程,的但只有当它尚未运行或拉开帷幕的。

In the producer threads, I need to kick off the consumer thread, but only if it's not already running or kicked off.

具体做法是:

public void BeginInvoke(Action method)
{
    //This runs on multiple background threads
    pendingActions.Enqueue(method);
    if (ProcessQueue hasn't been posted)
        uiContext.Post(ProcessQueue, null);
}
private void ProcessQueue(object unused)
{
    //This runs on the UI thread.
    Action current;
    while (pendingActions.TryDequeue(out current))
        current();
}

我使用.net 3.5,而不是4.0。 :(

I'm using .Net 3.5, not 4.0. :(

推荐答案

我创建了下面的类来做到这一点:

I created the following class to do this:

///<summary>Ensures that a block of code is only executed once at a time.</summary>
class Valve
{
    int isEntered;  //0 means false; 1 true

    ///<summary>Tries to enter the valve.</summary>
    ///<returns>True if no other thread is in the valve; false if the valve has already been entered.</returns>
    public bool TryEnter()
    {
        if (Interlocked.CompareExchange(ref isEntered, 1, 0) == 0)
            return true;
        return false;
    }

    ///<summary>Allows the valve to be entered again.</summary>
    public void Exit()
    {
        Debug.Assert(isEntered == 1);
        isEntered = 0;
    }
}

我用这样的:

I use it like this:

readonly Valve valve = new Valve();
public void BeginInvoke(Action method)
{
    pendingActions.Enqueue(method);
    if (valve.TryEnter())
        uiContext.Post(ProcessQueue, null);
}
private void ProcessQueue(object unused)
{
    //This runs on the UI thread.
    Action current;
    while (pendingActions.TryDequeue(out current))
        current();
    valve.Exit();
}

时的这种模式是否安全? 有没有更好的方式来做到这一点? 是否有该类的更正确的名字?

Is this pattern safe? Is there a better way to do this? Is there a more correct name for the class?