BlockingCollection实现单体程序内队列
Posted fanfan-90
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BlockingCollection实现单体程序内队列相关的知识,希望对你有一定的参考价值。
BlockingCollection可实现单体程序内队列功能,适合写日志、发邮件等并发高可异步的操作
BlockingCollection是一个线程安全的集合类,可提供以下功能:
-
实现制造者-使用者模式。
-
通过多线程并发添加和获取项。
-
可选最大容量。
-
集合为空或已满时通过插入和移除操作进行阻塞。
-
插入和移除“尝试”操作不发生阻塞,或在指定时间段内发生阻塞。
-
使用取消标记执行取消操作。
class Program { private static readonly BlockingCollection<string> _blockingQueue = new BlockingCollection<string>(); static void Main(string[] args) { Task.WaitAll(Task.Run(() => { Produce(); }), Task.Run(() => { Consume(); })); Console.ReadKey(); } private static void Produce() { try { if (!_blockingQueue.IsAddingCompleted) { for (int i = 0; i < 100; i++) //限制生产1000次 { var now = DateTime.Now.ToString(CultureInfo.InvariantCulture); Console.WriteLine($"第{i + 1}次生产! {now}"); _blockingQueue.Add(now); } } } catch { _blockingQueue.CompleteAdding(); //标记生产完成 } } private static void Consume() { int i = 1; try { while (!_blockingQueue.IsCompleted) { var x = _blockingQueue.Take(); Console.WriteLine($"第{i}次消费 {x}"); i++; Thread.Sleep(20); //故意减慢消费 } } catch { _blockingQueue.CompleteAdding(); } Console.WriteLine("异常,结束!!!"); } private static void DbUpDemo() { List<string> connectionStringList = new List<string> { "Data Source=192.168.0.116,30705;uid=sa;pwd=KI68oecJc0NpXwscxybK;Initial Catalog=test3;Pooling=true;Max Pool Size=1000;Min Pool Size=5;Connection Timeout=28800" }; string updateDbMessage = string.Empty; Console.WriteLine("更新数据库 开始。。。。"); bool updateDbResult = UpdateDBHelper.UpdateDb(connectionStringList, out updateDbMessage); if (!updateDbResult) { Console.WriteLine($"更新数据库 失败!-{updateDbMessage}"); } else { Console.WriteLine("更新数据库 成功!"); } } }
案例1:使用BlockingCollection做日志记录:
public class DBLoggerProcessor : IDisposable { private readonly BlockingCollection<string> _messageQueue = new BlockingCollection<string>(1024); private readonly Thread _writerThread; public DBLoggerProcessor() { // Start DB Logger queue processor _writerThread = new Thread(ProcessLogQueue) { IsBackground = true, Name = "DB logger queue processing thread" }; _writerThread.Start(); } public virtual void EnqueueMessage(string message) { if (!_messageQueue.IsAddingCompleted) { try { _messageQueue.Add(message); return; } catch (InvalidOperationException) { } } WriteMessage(message); } internal virtual void WriteMessage(string message) { //记录数据库 } private void ProcessLogQueue() { try { foreach (var message in _messageQueue.GetConsumingEnumerable()) { WriteMessage(message); } } catch { try { _messageQueue.CompleteAdding(); } catch { } } } public void Dispose() { _messageQueue.CompleteAdding(); try { _writerThread.Join(1500); } catch (ThreadStateException) { } } }
以上是关于BlockingCollection实现单体程序内队列的主要内容,如果未能解决你的问题,请参考以下文章
异步简析之BlockingCollection实现生产消费模式
csharp .NET 4 BlockingCollection的生产者/消费者实现
利用BlockingCollection实现生产者和消费者队列,实现写文本