今天我得到了here nice answer来解决我的问题。不幸的是,我忘记了如何锁定。
问题很简单 - 在服务器中,每个连接的客户端将获得1到500的唯一ID(可重用),这是客户端的最大值。
答案是创建一个qeue并使用等待元素进行新连接,并在释放时将它们返回。
我不确定我是否理解正确 - 我也应该使用500个元素(整数)初始化qeue并逐一取出它们并在释放后返回?
如果是这样,锁定在这里怎么样?我的问题主要是针对性能,因为我使用了锁。
答案 0 :(得分:1)
如果您可以使用Parallel Extensions,请转到ConcurrentQueue
如果你不能,你可以找到如何在Herb Sutter的this article中实现你自己的
顺便说一下,Jon Skeet的回答是告诉你只是尝试排队,如果空的生成和使用。当你完成id后,只需将它排入队列即可。没有提到500个ID。如果您需要限制为500个ID,那么您将需要使用500个ID初始化队列,然后在队列为空时,而不是生成新的队列。为此,consumer/producer pattern将更适合。
答案 1 :(得分:0)
我不明白你想做什么。
您可以为已使用的数字填充哈希表。
您可以将其存储在应用程序范围的变量中,并在访问该资源时使用Application.Lock和Application.Unlock方法。
答案 2 :(得分:0)
这样的东西?
/// <summary>
/// Thread safe queue of client ids
/// </summary>
internal class SlotQueue
{
private readonly AutoResetEvent _event = new AutoResetEvent(false);
private readonly Queue<int> _items = new Queue<int>();
private int _waitCount;
/// <summary>
/// Initializes a new instance of the <see cref="SlotQueue"/> class.
/// </summary>
/// <param name="itemCount">The item count.</param>
public SlotQueue(int itemCount)
{
// Create queue items
for (int i = 0; i < itemCount; ++i)
_items.Enqueue(i);
}
/// <summary>
/// Gets number of clients waiting in the queue.
/// </summary>
public int QueueSize
{
get { return _waitCount; }
}
/// <summary>
///
/// </summary>
/// <param name="waitTime">Number of milliseconds to wait for an id</param>
/// <returns></returns>
public int Deqeue(int waitTime)
{
// Thread safe check if we got any free items
lock (_items)
{
if (_items.Count > 0)
return _items.Dequeue();
}
// Number of waiting clients.
Interlocked.Increment(ref _waitCount);
// wait for an item to get enqueued
// false = timeout
bool res = _event.WaitOne(waitTime);
if (!res)
{
Interlocked.Decrement(ref _waitCount);
return -1;
}
// try to fetch queued item
lock (_items)
{
if (_items.Count > 0)
{
Interlocked.Decrement(ref _waitCount);
return _items.Dequeue();
}
}
// another thread got the last item between waitOne and the lock.
Interlocked.Decrement(ref _waitCount);
return -1;
}
/// <summary>
/// Enqueue a client ID
/// </summary>
/// <param name="id">Id to enqueue</param>
public void Enqueue(int id)
{
lock (_items)
{
_items.Enqueue(id);
if (_waitCount > 0)
_event.Set();
}
}
}