我如何确保只有一个线程可以执行某些操作?

我有多个线程将项添加到无锁队列。
然后由另一个线程处理这些项目。

在生产者线程中,我需要启动消费者线程, 但前提是它尚未运行或启动

特别:

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。 🙁

最简单的方法是使用Semaphore 。 它将具有队列大小的计数。

我创建了以下类来执行此操作:

 ///Ensures that a block of code is only executed once at a time. class Valve { int isEntered; //0 means false; 1 true ///Tries to enter the valve. ///True if no other thread is in the valve; false if the valve has already been entered. public bool TryEnter() { if (Interlocked.CompareExchange(ref isEntered, 1, 0) == 0) return true; return false; } ///Allows the valve to be entered again. public void Exit() { Debug.Assert(isEntered == 1); isEntered = 0; } } 

我这样使用它:

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

这种模式安全吗?
有一个更好的方法吗?
这个class的名字有更正确的名字吗?

这对你有用吗?

 volatile int running; //not a boolean to allow ProcessQueue to be reentrant. private void ProcessQueue(object unused) { do { ++running; Action current; while (pendingActions.TryDequeue(out current)) current(); --running; } while (pendingActions.Count != 0); } public void BeginInvoke(Action method) { pendingActions.Enqueue(method); if (running != 0) uiContext.Post(ProcessQueue, null); } 

为使用者线程创建第二个Dispatcher 。 然后,生产者线程可以使用该调度程序的BeginInvoke()方法将数据发送到使用者线程。 Dispatcher的队列取代pendingActions队列,并确保使用者线程一次只处理一个工作项。

而不是让生产者线程尝试协调启动和停止使用者线程,只需在任何生成器启动之前启动使用者线程,并让它闲置。 Dispatcher应该在需要时自动将其唤醒。