C# 如何创建FIFO/强信号量
我需要用C#编写自己的FIFO/强信号量,使用自己的信号量类作为基础。我找到了,但它不太正确,因为我还不应该使用Monitor.Enter/Exit 这些是我的常规信号量的方法,我想知道是否有一种简单的方法将其调整为FIFOC# 如何创建FIFO/强信号量,c#,.net,multithreading,concurrency,C#,.net,Multithreading,Concurrency,我需要用C#编写自己的FIFO/强信号量,使用自己的信号量类作为基础。我找到了,但它不太正确,因为我还不应该使用Monitor.Enter/Exit 这些是我的常规信号量的方法,我想知道是否有一种简单的方法将其调整为FIFO public virtual void Acquire() { lock (this) { while (uintTokens == 0) { Monitor.Wait(this);
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方法之外的所有内容定向到该信号量
为了获得类似队列的行为,我们需要一个队列对象,并且为了确保它在面对多线程访问时是安全的,我们将使用ConcurrentQueue
在这个队列中,我们将放置TaskCompletionSource
对象。当我们想让某个项目开始等待时,它可以创建一个TCS,将其添加到队列中,然后通知信号量异步弹出队列中的下一个项目,并在等待完成时将其标记为“已完成”。我们将知道,当队列中有项目时,将始终有相等或更少数量的延续
然后我们只需等待来自TCS的任务
我们还可以创建一个WaitAsync
方法来返回任务,只需返回它而不是等待它
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();
}
}
公共类信号量
{
私有信号量lim信号量;
私有并发队列=
新的ConcurrentQueue();
公共信号量相等(int initialCount)
{
信号量=新信号量lim(initialCount);
}
公共信号量相等(int initialCount,int maxCount)
{
信号量=新信号量lim(initialCount,maxCount);
}
公共无效等待()
{
WaitAsync().Wait();
}
公共任务WaitAsync()
{
var tcs=new TaskCompletionSource();
排队;排队(tcs);
semaphore.WaitAsync().ContinueWith(t=>
{
TaskCompletionSource弹出;
if(queue.TryDequeue(弹出))
popped.SetResult(true);
});
返回tcs.Task;
}
公开无效释放()
{
semaphore.Release();
}
}
我已经创建了一个FifosMaphore类,并且正在我的解决方案中成功地使用它。当前的限制是,它的行为类似于信号量(1,1)
在每个线程上:
fifoSemaphore.WaitOne();
//do work
fifoSemaphore.Release();
与您的问题不太相关,但您可能希望避免使用
lock(this)
code模式,因为它可能导致死锁。你一定是在用信号灯吗?您打算使用ConcurrentQueue作为基础吗?老师希望我们自己制作所有的实用程序,所以我们不使用任何内置的并发工具。不过我有自己的频道课。谢谢你的提示LB2,老师对它没有问题,但我还是会去修改它的。我检查了的源代码,看起来它已经是FIFO了。为等待创建的每个任务都存储在一个以双链表形式实现的队列中。可以找到一个FIFO信号量LIM
的基本实现,它具有一个public void-right(int-amount)
方法作为额外功能。其中有很多东西我们没有学过,这意味着我们并不打算使用它们。例如,等等。另外,我有自己的通道类(线程安全队列),我想可以使用它。@FreddieAppsHero欢迎您使用自己的工具使用相同的模型,如果您愿意的话。我自己的信号量缺少WaitAsync,可能不赞成再扩展它。@FreddieAppsHero这当然是您的决定。
FifoSemaphore fifoSemaphore = new FifoSemaphore();
fifoSemaphore.WaitOne();
//do work
fifoSemaphore.Release();