zoukankan      html  css  js  c++  java
  • C#中奇怪的Queue <T> 行为!

    小弟希望通过Queue <T>泛型类实现多线程异步操作, 但却在实际应用中, 遇到了十分奇怪的问题

    1, 调用Queue <T>.Enqueue 方法时, 会不定时抛出ArgumentException, 错误消息为"源数组长度不足。请检查 srcIndex 和长度以及数组的下限。"
    2, 调用Queue <T>.Dequeue 方法时, 会不定时返回0或null, 但队列中确从未添加过0或null.

    在网上搜索了一遍, 没有找到相关资料, 只有在此劳烦园子里各位高手大哥相助了, 代码贴在下面, 具体的问题已标注在注释里面, 如下:

    /// <summary>
    /// 此类表示任务队列, 使用独立线程执行
    /// </summary>
    class TaskQueue
    {
        
    /// <summary>
        
    /// 私用默认构造函数, 此处初始化任务执行线程.
        
    /// </summary>
        private TaskQueue()
        {
            Thread tdTask 
    = new Thread(new ThreadStart(this.doTask));
            tdTask.IsBackground 
    = true;
            tdTask.Start();
        }

        
    /// <summary>
        
    /// 触发执行任务的事件.
        
    /// </summary>
        private ManualResetEvent _meventDoTask = new ManualResetEvent(false);

        
    /// <summary>
        
    /// 要执行的任务队列
        
    /// </summary>
        
    /// <remarks>
        
    /// 注意: 此处设置了Queue<T>的容量为100万
        
    /// , 如果不设置此容量 在调用 Queue<T>.Enqueue 方法时, 会不定时抛出异常ArgumentException
        
    /// , 消息为"源数组长度不足。请检查 srcIndex 和长度以及数组的下限。"
        
    /// </remarks>
        private Queue<int> _taskQueue = new Queue<int>(1024 * 1024);

        
    /// <summary>
        
    /// 将任务编号排入队列, 并触发执行.
        
    /// </summary>
        
    /// <param name="taskId">任务编号</param>
        private void QueueTask(int taskId)
        {
            
    if (taskId != 0)
            {
                
    //注意: taskId 在排入队列前, 已做了非0验证.
                this._taskQueue.Enqueue(taskId);
                
    this._meventDoTask.Set();
            }
        }

        
    /// <summary>
        
    /// 在此方法中, 执行任务
        
    /// </summary>
        private void doTask()
        {
        RETRY:
            
    this._meventDoTask.WaitOne();
            
    this._meventDoTask.Reset();

            
    while (this._taskQueue.Count != 0)
            {
                
    //注意: _taskQueue 中从来不加入值为0的项, 但此处用Dequeue()得到的taskId依然会随机出现0值.
                
    //另外, 经测试, 如果 _taskQueue 存储的不是值类型, 而是 类类型, 则Dequeue()方法得到的项会随便出现null.
                int taskId = this._taskQueue.Dequeue();

                
    if (taskId != 0)
                {
                    
    //do the task
                }
            }

            
    goto RETRY;
        }
    }
  • 相关阅读:
    【集训队作业2018】不可名状
    【UTR #3】量子破碎
    【清华集训2016】你的生命已如风中残烛
    【清华集训2016】如何优雅地求和
    玩转大数据系列之Apache Pig高级技能之函数编程(六)
    ElasticSearch入门之彼行我释(四)
    玩转大数据系列之Apache Pig如何与Apache Solr集成(二)
    玩转大数据之Apache Pig如何与Apache Lucene集成
    如何学好一门编程语言或技术?
    2015年春节往事小记
  • 原文地址:https://www.cnblogs.com/Betree/p/1569974.html
Copyright © 2011-2022 走看看