• C# 应用


    1. 功能

    模拟一个生产、消费的过程,不过这里没有做消息自动通知,而是消费者自己定时过去取。
    一般的生产环境应该是在有新消息产生时,将新消息发送给消费者。
    拿下面例子来举例,可在数据入队时,调用一个 event 方法,event 触发消费者的方法。
    如果是不同设备之间的订阅,要么自己写 http 接受/请求 去实现订阅、通知,要么用成熟的 MQ。

    2. 代码实现

    public partial class QueueWindow : Window
    {
        Queue<int> _queueNum;
    
        public int Num
        {
            get { return (int)GetValue(NumProperty); }
            set { SetValue(NumProperty, value); }
        }
    
        public static readonly DependencyProperty NumProperty =
            DependencyProperty.Register("Num", typeof(int), typeof(QueueWindow), new PropertyMetadata(1));
    
        CancellationTokenSource _source = new CancellationTokenSource();
    
        int _beginNum = 1;
        int _takeTimeForGetData = 3; // 耗时
        int _getLength = 25; // 从数据库取出的数据的长度
        int _sleepTime = 10; // 定时从数据库取数据的间隔
        int _intervalSpeed = 1; // 从队列取出数据的频率
    
        public QueueWindow()
        {
            InitializeComponent();            
    
            this.tb.SetBinding(TextBlock.TextProperty, new Binding("Num") { Source = this });
    
            Test();
        }
    
        public void Test()
        {
            RefreshCache();
    
            GetDataTask();
    
            ShowDataTask();
        }
    
        public void RefreshCache()
        {
            if (_queueNum == null)
            {
                _queueNum = new Queue<int>();
            }
            else
            {
                _queueNum.Clear();
            }
        }               
    
        /// <summary>
        /// 定时从数据库获取数据并入队
        /// </summary>
        void GetDataTask()
        {
            Task.Factory.StartNew(() =>
            {
                while (!_source.IsCancellationRequested)
                {
                    // 取数据的耗时
                    Thread.Sleep(_takeTimeForGetData * 1000);
    
                    // 模拟从数据库取出数据,并将数据放入队列
                    foreach (int i in Enumerable.Range(_beginNum, _getLength))
                    {
                        EnQueue(i);
                    }
                    _beginNum = _beginNum + _getLength;
    
                    // 定时
                    Thread.Sleep(_sleepTime * 1000);
                }
            });
        }
    
        /// <summary>
        /// 定时从队列中取出一个数据并展示
        /// </summary>
        void ShowDataTask()
        {
            Task.Factory.StartNew(() =>
            {
                while (!_source.IsCancellationRequested)
                {
    
                    Tuple<bool, int> res = DeQueue();
                    if (res.Item1)
                    {
                        App.Current.Dispatcher.Invoke(new Action(() =>
                        {
                            Num = res.Item2;
                        }));
                    }
    
                    // 根据每次读取的时间间隔、读取耗时、返回结果的长度来决定 出队 的时间间隔
                    double mill = (double)(_takeTimeForGetData + _sleepTime) / (double)_getLength;
                    Thread.Sleep((int)(mill * 1000));
                }
            }, TaskCreationOptions.LongRunning);
        }
    
        object _cacheLockObj = new object();
    
        /// <summary>
        /// 入队
        /// </summary>
        /// <param name="num"></param>
        public void EnQueue(int num)
        {
            lock (_cacheLockObj)
            {
                if (_queueNum == null) return;
    
                _queueNum.Enqueue(num);
    
                // 当需要控制队列的长度时,通过一定的策略删除掉部分数据
            }            
        }
    
        /// <summary>
        /// 出队
        /// </summary>
        /// <returns></returns>
        public Tuple<bool, int> DeQueue()
        {
            bool hasNum = false;
            int num = 0;
    
            lock (_cacheLockObj)
            {
                if (_queueNum != null && _queueNum.Count > 0)
                {
                    num = _queueNum.Dequeue();
                    hasNum = true;
                    Console.WriteLine(string.Join(", ", _queueNum.ToList()));
                }                
            }
    
            return new Tuple<bool, int>(hasNum, num);
        }
    
        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
    }
    
  • 相关阅读:
    利用Percona monitoring for zabbix监控MySQL
    SQL Server复制故障(1)
    SQL Server事务复制搭建与同步经验
    达梦7入门技术总结--DCA级别
    机器学习:双聚类算法
    脑洞篇之我们生活在9维世界
    自动化运维:使用flask+mysql+highcharts搭建监控平台
    深度学习:Keras入门(二)之卷积神经网络(CNN)
    深度学习:Keras入门(一)之基础篇
    机器学习:特征选择
  • 原文地址:https://www.cnblogs.com/MichaelLoveSna/p/14502052.html
Copyright © 2020-2023  润新知