Sla*_*ngy 5 .net c# concurrency multithreading
我需要在C#中编写自己的FIFO /强信号量,使用我自己的信号量类作为基础.我找到了这个例子,但它不是很正确,因为我不应该使用Monitor.Enter/Exit.
这些是我的常规信号量的方法,我想知道是否有一种简单的方法可以使它适应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);
}
}
Run Code Online (Sandbox Code Playgroud)
Ser*_*rvy 19
所以SemaphoreSlim给我们一个很好的起点,所以我们首先将其中一个包装在一个新类中,然后将等待方法中的所有内容指向该信号量.
为了获得类似行为的队列,我们需要一个队列对象,并确保它在多线程访问时是安全的,我们将使用ConcurrentQueue.
在这个队列中,我们将放置TaskCompletionSource对象.当我们想要开始等待时,它可以创建一个TCS,将其添加到队列中,然后通知信号量以异步方式弹出队列中的下一个项目,并在等待完成时将其标记为"已完成".我们知道,队列中有项目总会有相同或更少数量的延续.
然后我们等待Task来自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();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3511 次 |
| 最近记录: |