autoresetevent java_AutoResetEvent未正确阻止

我有一个线程,它创建可变数量的工作线程并在它们之间分配任务 . 这是通过向线程传递一个TaskQueue对象来解决的,您将在下面看到它的实现 .

这些工作线程只是迭代它们给出的TaskQueue对象,执行每个任务 .

private class TaskQueue : IEnumerable

{

public int Count

{

get

{

lock(this.tasks)

{

return this.tasks.Count;

}

}

}

private readonly Queue tasks = new Queue();

private readonly AutoResetEvent taskWaitHandle = new AutoResetEvent(false);

private bool isFinishing = false;

private bool isFinished = false;

public void Enqueue(Task task)

{

Log.Trace("Entering Enqueue, lock...");

lock(this.tasks)

{

Log.Trace("Adding task, current count = {0}...", Count);

this.tasks.Enqueue(task);

if (Count == 1)

{

Log.Trace("Count = 1, so setting the wait handle...");

this.taskWaitHandle.Set();

}

}

Log.Trace("Exiting enqueue...");

}

public Task Dequeue()

{

Log.Trace("Entering Dequeue...");

if (Count == 0)

{

if (this.isFinishing)

{

Log.Trace("Finishing (before waiting) - isCompleted set, returning empty task.");

this.isFinished = true;

return new Task();

}

Log.Trace("Count = 0, lets wait for a task...");

this.taskWaitHandle.WaitOne();

Log.Trace("Wait handle let us through, Count = {0}, IsFinishing = {1}, Returned = {2}", Count, this.isFinishing);

if(this.isFinishing)

{

Log.Trace("Finishing - isCompleted set, returning empty task.");

this.isFinished = true;

return new Task();

}

}

Log.Trace("Entering task lock...");

lock(this.tasks)

{

Log.Trace("Entered task lock, about to dequeue next item, Count = {0}", Count);

return this.tasks.Dequeue();

}

}

public void Finish()

{

Log.Trace("Setting TaskQueue state to isFinishing = true and setting wait handle...");

this.isFinishing = true;

if (Count == 0)

{

this.taskWaitHandle.Set();

}

}

public IEnumerator GetEnumerator()

{

while(true)

{

Task t = Dequeue();

if(this.isFinished)

{

yield break;

}

yield return t;

}

}

IEnumerator IEnumerable.GetEnumerator()

{

return GetEnumerator();

}

}

正如您所看到的,我正在使用 AutoResetEvent 对象来确保工作线程不会过早退出,即在获取任何任务之前 .

简而言之:

主线程通过Enqeueue任务到TaskQueue为线程分配任务

主线程通过调用TaskQueue的Finish()方法通知线程不再执行任务

工作线程通过调用TaskQueue的Dequeue()方法检索分配给它的下一个任务

问题是 Dequeue ()方法经常 throws an InvalidOperationException ,说Queue是空的 . 正如您所看到的,我添加了一些日志记录,事实证明,AutoResetEvent不会阻止Dequeue(),即使没有调用其Set()方法 .

据我了解,调用AutoResetEvent.Set()将允许等待线程继续(之前调用AutoResetEvent.WaitOne()),然后自动调用AutoResetEvent.Reset(),阻止下一个服务员 .

那有什么不对?我弄错了吗?我某处有错误吗?我现在坐在这上面3个小时,但我无法弄清楚出了什么问题 . 请帮我!

非常感谢你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值