c#中的队列是如何工作的? (允许的类型、初始化和字段)
Queue in c# how does it work? (types allowed, initialization and fields)
我正在用 C# 编写一个软件,但我无法理解队列。这是简化的情况:我已经有一个服务器和一个通信接口。服务器以一定的速率连续喷出数据,我想将其放入队列类型的缓冲区(数据进出的顺序非常重要,因为它将被解码,然后通过不同的方式发送到数据库联系)。问题是:当我尝试创建一个 class 来保存我的缓冲区(以及其他数据)时,我将其定义为
public class BufferingClass
{
public Queue<string[]> ServerDataBuffer;
// rest of the code
}
但我收到错误 Queue does not exist in current context
我可以定义为
public class BufferingClass
{
public Queue ServerDataBuffor
// rest of the code
}
令人惊讶的是,将不同类型的对象分配到像这样定义的队列(如 INT
STRING
BOOL
或其他 classes 的数组)是可以的编译器方面(我胆子不够运行这样的程序)
所以这是我的问题。队列到底是什么?我不是在问一些琐碎的事情,比如它是一个 FIFO 集合。我只是感到惊讶,它不像该语言中的其他所有内容那样强类型化,即使它看起来像一个列表并且闻起来像一个列表,但以类似的方式定义它会引发编译器的危险信号。
另外Producer-Consumer问题是如何处理的?我知道,从生产者的角度来看,如果我继续将数据泵入我的 Queue
,那么 OS 只会将其容量加倍,直到 运行 内存不足,甚至更多 space不能分配。但是,当缓冲区为空时调用 dequeue 时,会向代码发送什么信号?还是我必须处理 manually
?特别是当一个线程正在添加到队列而另一个线程正在使用它时。
Public Queue<string[]> ServerDataBuffer;
这不是有效的 C# 行,这必须是 public
,而不是 Public
。
我认为这是一个简单的错字。而且,正如@JonSkeet 提到的,有两个不同的 类、one of them is a generic, and second is not. Moreover, there is a ConcurrentQueue
,它们面向多线程环境并且也是通用的。内部算法非常复杂,此处不再尝试解释。您可以找到它们的来源。
并发队列示例 (from MSDN):
// Construct a ConcurrentQueue.
ConcurrentQueue<int> cq = new ConcurrentQueue<int>();
// Populate the queue.
for (int i = 0; i < 10000; i++) cq.Enqueue(i);
// Peek at the first element.
int result;
if (!cq.TryPeek(out result))
{
Console.WriteLine("CQ: TryPeek failed when it should have succeeded");
}
else if (result != 0)
{
Console.WriteLine("CQ: Expected TryPeek result of 0, got {0}", result);
}
int outerSum = 0;
// An action to consume the ConcurrentQueue.
Action action = () =>
{
int localSum = 0;
int localValue;
while (cq.TryDequeue(out localValue)) localSum += localValue;
Interlocked.Add(ref outerSum, localSum);
};
// Start 4 concurrent consuming actions.
Parallel.Invoke(action, action, action, action);
Console.WriteLine("outerSum = {0}, should be 49995000", outerSum);
并发 FIFO 队列的另一种实现是 BufferBlock
class from TPL Dataflow library。
如果您对 Producer/Consumer
大小有限的实现感兴趣,请参阅 BlockingCollection
class implementing IProducerConsumerCollection<T>
如您所见,有很多针对您的问题的通用解决方案。阅读选项并根据需要选择它们。
我正在用 C# 编写一个软件,但我无法理解队列。这是简化的情况:我已经有一个服务器和一个通信接口。服务器以一定的速率连续喷出数据,我想将其放入队列类型的缓冲区(数据进出的顺序非常重要,因为它将被解码,然后通过不同的方式发送到数据库联系)。问题是:当我尝试创建一个 class 来保存我的缓冲区(以及其他数据)时,我将其定义为
public class BufferingClass
{
public Queue<string[]> ServerDataBuffer;
// rest of the code
}
但我收到错误 Queue does not exist in current context
我可以定义为
public class BufferingClass
{
public Queue ServerDataBuffor
// rest of the code
}
令人惊讶的是,将不同类型的对象分配到像这样定义的队列(如 INT
STRING
BOOL
或其他 classes 的数组)是可以的编译器方面(我胆子不够运行这样的程序)
所以这是我的问题。队列到底是什么?我不是在问一些琐碎的事情,比如它是一个 FIFO 集合。我只是感到惊讶,它不像该语言中的其他所有内容那样强类型化,即使它看起来像一个列表并且闻起来像一个列表,但以类似的方式定义它会引发编译器的危险信号。
另外Producer-Consumer问题是如何处理的?我知道,从生产者的角度来看,如果我继续将数据泵入我的 Queue
,那么 OS 只会将其容量加倍,直到 运行 内存不足,甚至更多 space不能分配。但是,当缓冲区为空时调用 dequeue 时,会向代码发送什么信号?还是我必须处理 manually
?特别是当一个线程正在添加到队列而另一个线程正在使用它时。
Public Queue<string[]> ServerDataBuffer;
这不是有效的 C# 行,这必须是 public
,而不是 Public
。
我认为这是一个简单的错字。而且,正如@JonSkeet 提到的,有两个不同的 类、one of them is a generic, and second is not. Moreover, there is a ConcurrentQueue
,它们面向多线程环境并且也是通用的。内部算法非常复杂,此处不再尝试解释。您可以找到它们的来源。
并发队列示例 (from MSDN):
// Construct a ConcurrentQueue.
ConcurrentQueue<int> cq = new ConcurrentQueue<int>();
// Populate the queue.
for (int i = 0; i < 10000; i++) cq.Enqueue(i);
// Peek at the first element.
int result;
if (!cq.TryPeek(out result))
{
Console.WriteLine("CQ: TryPeek failed when it should have succeeded");
}
else if (result != 0)
{
Console.WriteLine("CQ: Expected TryPeek result of 0, got {0}", result);
}
int outerSum = 0;
// An action to consume the ConcurrentQueue.
Action action = () =>
{
int localSum = 0;
int localValue;
while (cq.TryDequeue(out localValue)) localSum += localValue;
Interlocked.Add(ref outerSum, localSum);
};
// Start 4 concurrent consuming actions.
Parallel.Invoke(action, action, action, action);
Console.WriteLine("outerSum = {0}, should be 49995000", outerSum);
并发 FIFO 队列的另一种实现是 BufferBlock
class from TPL Dataflow library。
如果您对 Producer/Consumer
大小有限的实现感兴趣,请参阅 BlockingCollection
class implementing IProducerConsumerCollection<T>
如您所见,有很多针对您的问题的通用解决方案。阅读选项并根据需要选择它们。