小弟希望通过Queue <T>泛型类实现多线程异步操作, 但却在实际应用中, 遇到了十分奇怪的问题
1, 调用Queue <T>.Enqueue 方法时, 会不定时抛出ArgumentException, 错误消息为"源数组长度不足。请检查 srcIndex 和长度以及数组的下限。"
2, 调用Queue <T>.Dequeue 方法时, 会不定时返回0或null, 但队列中确从未添加过0或null.
在网上搜索了一遍, 没有找到相关资料, 只有在此劳烦园子里各位高手大哥相助了, 代码贴在下面, 具体的问题已标注在注释里面, 如下:
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;
}
}
/// 此类表示任务队列, 使用独立线程执行
/// </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;
}
}