小弟希望通过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;
    }
}
posted on 2009-09-19 13:51  邢政  阅读(2617)  评论(8编辑  收藏  举报