队列是其元素以先进先出的方式处理的集合。先放入队列的元素会先读取。
队列使用System.Collections.Generic 名称空间中的泛型类Queue<T>实现。在内部,Queue<T>类使用T类型的数组,这类似于List<T>类型。它实现ICollection和IEnumerable<T>接口,但没有实现ICollection<T>接口,因为这个接口定义的Add()和Remove()
方法不能用于队列。
Queue<T>类的方法如下:
count:返回队列中元素个数;
Enqueue:在队列一端添加一个元素;
Dequeue:在队列的头部读取和删除元素。如果在调用Dequeue()方法是,队列中不在有元素,就抛出一个InvalidOperationException类型的异常;
Peek:从队列的头部读取一个元素,但不删除它;
TrimExcess:重新设置队列的容量。Dequeue()方法从队列中删除元素,但它不会重新设置队列的容量。要从队列的头部去除空元素,应使用TrimExcess()方法。
实现队列的案例:
/// <summary>
/// 接口文档
/// </summary>
public interface IDocument
{
string Title { get; set; }
string Content { get; set; }
}
/// <summary>
/// 文档
/// </summary>
public class Document : IDocument
{
public Document() { }
public Document(string title, string content)
{
Title = title;
Content = content;
}
public string Title { get; set; }
public string Content { get; set; }
}
/// <summary>
/// 文档管理
/// </summary>
/// <typeparam name="T"></typeparam>
public class DocumentManager<T> where T : IDocument
{
//定义存储集合
private readonly Queue<T> documentQueue = new Queue<T>();
/// <summary>
/// 对集合进行添值操作
/// </summary>
/// <param name="doc"></param>
public void AddDocument(T doc)
{
lock (this)
{
documentQueue.Enqueue(doc);
}
}
public bool IsDocumentAvailable => documentQueue.Count > 0;
public T GetDocument()
{
T doc = default(T);
lock (this)
{
doc = documentQueue.Dequeue();
}
return doc;
}
public void DisplayAllDocuments()
{
foreach (T doc in documentQueue)
{
Console.WriteLine(doc.Title);
}
}
}
/// <summary>
/// 文档执行过程
/// </summary>
public class ProcessDocuments
{
private DocumentManager<Document> _documentManager;
/// <summary>
/// Start方法访问
/// </summary>
/// <param name="dm"></param>
public static void Start(DocumentManager<Document> dm)
{
//对线程池上指定工作排队,并返回函数对应的任务代理
Task.Run(new ProcessDocuments(dm).Run);
}
protected ProcessDocuments(DocumentManager<Document> dm)
{
if (dm == null)
{
throw new ArgumentNullException(nameof(dm));
}
_documentManager = dm;
}
/// <summary>
/// 无限循环取队列中的信息
/// </summary>
/// <returns></returns>
protected async Task Run()
{
while (true)
{
if (_documentManager.IsDocumentAvailable)
{
Document doc = _documentManager.GetDocument();
Console.WriteLine($"Processing document {doc.Title}");
}
await Task.Delay(new Random().Next(20));
}
}
}
//调用方式
var dm = new DocumentManager<Document>();
ProcessDocuments.Start(dm);
for (int i = 0; i < 10; i++)
{
var doc = new Document($"Doc {i.ToString()}", "content");
dm.AddDocument(doc);
Console.WriteLine($"Added document {doc.Title}");
Thread.Sleep(new Random().Next(20));
}
Console.ReadLine();