如何创建FIFO/强信号量 [英] How to create a FIFO/strong semaphore

查看:72
本文介绍了如何创建FIFO/强信号量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用自己的信号量类作为基础,用C#编写自己的FIFO/强信号量.我发现此示例,但这不太正确,因为我不应该使用Monitor.输入/退出.

I need to code my own FIFO/strong semaphore in C#, using a semaphore class of my own as a base. I found this example, but it's not quite right since I'm not supposed to be using Monitor.Enter/Exit yet.

这些是我的常规信号量的方法,我想知道是否有一种简单的方法可以将其调整为FIFO.

These are the methods for my regular semaphore, and I was wondering if there was a simple way to adapt it to be FIFO.

public virtual void Acquire()
{

    lock (this)
    {

        while (uintTokens == 0)
        {

            Monitor.Wait(this);

        }

        uintTokens--;

    }

}

public virtual void Release(uint tokens = 1)
{

    lock (this)
    {

        uintTokens += tokens;
        Monitor.PulseAll(this);

    }

}

推荐答案

所以SemaphoreSlim为我们提供了一个很好的起点,因此,我们将其中一个包装在新类中,并指导除wait方法外的所有内容,以此开始那个信号量.

So SemaphoreSlim gives us a good starting place, so we'll begin by wrapping one of those in a new class, and directing everything but the wait method to that semaphore.

要获得类似行为的队列,我们​​需要一个队列对象,并确保在面对多线程访问时它是安全的,我们将使用ConcurrentQueue.

To get a queue like behavior we'll want a queue object, and to make sure it's safe in the face of multithreaded access, we'll use a ConcurrentQueue.

在此队列中,我们将放置TaskCompletionSource个对象.当我们要开始等待时,可以创建一个TCS,将其添加到队列中,然后通知信号量从队列中异步弹出下一个项目,并在等待结束时将其标记为完成".我们会知道,由于队列中有项目,因此连续的次数总是相等或更少.

In this queue we'll put TaskCompletionSource objects. When we want to have something start waiting it can create a TCS, add it to the queue, and then inform the semaphore to asynchronously pop the next item off of the queue and mark it as "completed" when the wait finishes. We'll know that there will always be an equal or lesser number of continuations as there are items in the queue.

然后我们只需等待TCS中的Task.

Then we just wait on the Task from the TCS.

我们还可以简单地创建一个返回任务的WaitAsync方法,方法是只返回而不是等待它.

We can also trivially create a WaitAsync method that returns a task, by just returning it instead of waiting on it.

public class SemaphoreQueue
{
    private SemaphoreSlim semaphore;
    private ConcurrentQueue<TaskCompletionSource<bool>> queue =
        new ConcurrentQueue<TaskCompletionSource<bool>>();
    public SemaphoreQueue(int initialCount)
    {
        semaphore = new SemaphoreSlim(initialCount);
    }
    public SemaphoreQueue(int initialCount, int maxCount)
    {
        semaphore = new SemaphoreSlim(initialCount, maxCount);
    }
    public void Wait()
    {
        WaitAsync().Wait();
    }
    public Task WaitAsync()
    {
        var tcs = new TaskCompletionSource<bool>();
        queue.Enqueue(tcs);
        semaphore.WaitAsync().ContinueWith(t =>
        {
            TaskCompletionSource<bool> popped;
            if (queue.TryDequeue(out popped))
                popped.SetResult(true);
        });
        return tcs.Task;
    }
    public void Release()
    {
        semaphore.Release();
    }
}

这篇关于如何创建FIFO/强信号量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆