100分请高人指点,为什么我的多线程队列会出错!

joykai 2006-11-04 02:17:33
我自己写了一个多线程用的队列模版,在插入和取出的速度相同的情况下不出错,可是在取出速度大于插入速度的时候,就会报Debug Assertion Failed错误,我已经知道是因为取了空值的缘故!可是我就是不知道的我的模版错在那儿了!请高人指点!下面是我的多线程模版类:


template<class Type>
class CQueue
{
private:

CList<Type,Type&>m_List;
CRITICAL_SECTION m_lock;
HANDLE m_hOutEvent;
HANDLE m_hInEvent;
int m_nMax;
BOOL m_bDrop;

public:

//初始化队列
CQueue(int nQueueLength=10,BOOL bDrop=FALSE)
{
m_nMax=nQueueLength;
m_bDrop=bDrop;
InitializeCriticalSection(&m_lock);
m_hInEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
assert(m_hInEvent!=NULL);
m_hOutEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
assert(m_hOutEvent!=NULL);
}

//销毁队列
~CQueue()
{
DeleteCriticalSection(&m_lock);
CloseHandle(m_hInEvent);
CloseHandle(m_hOutEvent);
m_List.RemoveAll();
}

//插入元素item到队尾
void EnQueue(Type item)
{
EnterCriticalSection(&m_lock);
if (m_List.GetCount()>=m_nMax)
{
ResetEvent(m_hInEvent);
LeaveCriticalSection(&m_lock);
if (m_bDrop) return;
if (WaitForSingleObject(m_hInEvent,INFINITE)!= WAIT_OBJECT_0)
assert(FALSE);
EnterCriticalSection(&m_lock);
}
m_List.AddTail(item);
SetEvent(m_hOutEvent);
LeaveCriticalSection(&m_lock);
}

//删除队列的队头元素,并返回元素
Type DeQueue()
{
Type type;

EnterCriticalSection(&m_lock);

// 如果队列为空
if (m_List.IsEmpty())
{
ResetEvent(m_hOutEvent);
LeaveCriticalSection(&m_lock);
if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
EnterCriticalSection(&m_lock);
}
type = m_List.RemoveHead();
SetEvent(m_hInEvent);
LeaveCriticalSection(&m_lock);

return type;
}

//取得队列头部元素
Type GetHead()
{
Type head;
EnterCriticalSection(&m_lock);
head=m_List.GetHead();
LeaveCriticalSection(&m_lock);
return head;
}

//返回队列长度
int GetLength()
{
int nCount = 0;
EnterCriticalSection(&m_lock);
nCount = m_List.GetCount();
LeaveCriticalSection(&m_lock);
return nCount;
}

//清空队列
void ClearQueue()
{
EnterCriticalSection(&m_lock);
m_List.RemoveAll();
LeaveCriticalSection(&m_lock);
}

//检测队列是否为空,为空返回TRUE,不空返回FALSE;
BOOL IsEmpty()
{
BOOL bEmpty;
EnterCriticalSection(&m_lock);
bEmpty=m_List.IsEmpty();
LeaveCriticalSection(&m_lock);
return bEmpty;
}

//检测队列是否为满
BOOL IsFull()
{
BOOL bFull;
EnterCriticalSection(&m_lock);
bFull=(m_List.GetCount()>=m_nMax);
LeaveCriticalSection(&m_lock);
return bFull;
}
};
...全文
457 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Analyst 2007-01-09
  • 打赏
  • 举报
回复
我完全没看懂你这两段代码的意图是什么
ResetEvent(m_hInEvent);
LeaveCriticalSection(&m_lock);
if (m_bDrop) return;
if (WaitForSingleObject(m_hInEvent,INFINITE)!= WAIT_OBJECT_0)


ResetEvent(m_hOutEvent);
LeaveCriticalSection(&m_lock);
if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)

自己激发消息自己去等待?有什么意义?根据你的意图应该把把两个Wait事件对调一下
MikeChen2003 2007-01-09
  • 打赏
  • 举报
回复
忘了在else 下的LeaveCriticalSection(&m_lock);之后加个break
MikeChen2003 2007-01-09
  • 打赏
  • 举报
回复
EnterCriticalSection(&m_lock);

// 如果队列为空
if (m_List.IsEmpty())
{
ResetEvent(m_hOutEvent);
LeaveCriticalSection(&m_lock);
if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
EnterCriticalSection(&m_lock);
}
type = m_List.RemoveHead();
SetEvent(m_hInEvent);
LeaveCriticalSection(&m_lock);


这里有问题,如果有两个线成同时到了这句话if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0),那么如果新来一个元素,就会出问题。改成这样好一点


while(1)
{
EnterCriticalSection(&m_lock);
// 如果队列为空
if (m_List.IsEmpty())
{
ResetEvent(m_hOutEvent);
LeaveCriticalSection(&m_lock);
if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
}
else
{
type = m_List.RemoveHead();
SetEvent(m_hInEvent);
LeaveCriticalSection(&m_lock);
}
}
JonathanS666 2007-01-08
  • 打赏
  • 举报
回复
为什么用三个同步对象,一个就够了,同一时刻只有一个线程操作这个队列。
yjgx007 2007-01-07
  • 打赏
  • 举报
回复
没怎么看代码,最后用个等待函数等待消息到达,建议用
MsgWaitForMultipleObjectsEx
ReverseEngineering 2007-01-06
  • 打赏
  • 举报
回复
可能是同步!
chehw 2006-11-26
  • 打赏
  • 举报
回复
你的线程同步有问题。
假设m_list中还剩一个元素时,同时有两个线程要Dequeue, 这时两个线程均不会执
if (m_List.IsEmpty()){}中的代码
而直接跳至type = m_List.RemoveHead();



dch4890164 2006-11-26
  • 打赏
  • 举报
回复
用boundchecker软件查查看!
基本上这是最后一招了!
lemon_wei 2006-11-26
  • 打赏
  • 举报
回复
光看一下子也看不出来呀,在debug状态下按F5运行,等到出错后按Alt+7看堆栈中显示的是哪个函数出错,双击那个函数定位到源代码中,再来分析。
joykai 2006-11-05
  • 打赏
  • 举报
回复
这样没用的!谢谢!
joykai 2006-11-04
  • 打赏
  • 举报
回复
没有知道原因了么?
joykai 2006-11-04
  • 打赏
  • 举报
回复
回复BoXoft() :
报的是报Debug Assertion Failed错误!

我已经知道是去了空数据的问题!我目前是想知道我的程序在DeQueue的时候哪儿出了逻辑错误!谢谢!
joykai 2006-11-04
  • 打赏
  • 举报
回复
回复yangnix(yanxingli) :
程序到哪儿我是希望程序继续执行下去,因为没有数据,即数据为空得时候,我希望线程等待!当等到有数据事件发生得时候,程序就可以继续执行下去了!所以没有用return NULL返回!
鄢老 2006-11-04
  • 打赏
  • 举报
回复
在Type DeQueue()函数里:
if (m_List.IsEmpty())
{
ResetEvent(m_hOutEvent);
LeaveCriticalSection(&m_lock);
if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)
{
//ASSERT(FALSE);
return NULL; //如果这句不写,它还要往下执行删除的操作
}
EnterCriticalSection(&m_lock);

}
yjgx007 2006-11-04
  • 打赏
  • 举报
回复
if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);

你是说这段吗?
DentistryDoctor 2006-11-04
  • 打赏
  • 举报
回复
什么断言?
BoXoft 2006-11-04
  • 打赏
  • 举报
回复
Debug Assertion Failed 应该有对话框弹出来。里面的内容是什么?
sosonokia 2006-11-04
  • 打赏
  • 举报
回复
你把
m_hInEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
assert(m_hInEvent!=NULL);
m_hOutEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

中的CreateEvent的第2个参数改为TRUE试试

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧