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

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

问题描述

我需要在 C# 中编写我自己的 FIFO/强信号量,使用我自己的信号量类作为基础.我找到了这个例子,但这不太正确,因为我不应该使用 Monitor.Enter/Exit.

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 为我们提供了一个很好的起点,所以我们将首先将其中的一个包装到一个新类中,并指导除了该信号量的等待方法之外的所有内容.

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

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

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