我自己写了一个多线程用的队列模版,在插入和取出的速度相同的情况下不出错,可是在取出速度大于插入速度的时候,就会报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;
}
};
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;
}
};
解决方案 »
- BSTR与_bstr_t转换 类型与类如何可以转换
- 请教如何对话框中竖条效果
- 关于CreateFileMapping 参数效率的问题
- CListBox能否批添加字符串的?只能用AddString一行一行的加嘛?
- 函数如此声明,void func(void **a); char *info ,怎么传进去?? func((void**)info)对么?
- ADO数据库记录对象问题,很不解
- 谁能介绍一下MCI怎么用?
- {{ }}的意思?
- 如何使CpropertyPage上的Picture上的图像重绘?
- 本人只有一dll文件,知道其中实现一组件,在vc中怎么使用?
- 怎么样检测internet掉线?
- 关于 InsertItem第一个参数问题
ASSERT(FALSE);你是说这段吗?
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);
}
程序到哪儿我是希望程序继续执行下去,因为没有数据,即数据为空得时候,我希望线程等待!当等到有数据事件发生得时候,程序就可以继续执行下去了!所以没有用return NULL返回!
报的是报Debug Assertion Failed错误!我已经知道是去了空数据的问题!我目前是想知道我的程序在DeQueue的时候哪儿出了逻辑错误!谢谢!
m_hInEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
assert(m_hInEvent!=NULL);
m_hOutEvent=CreateEvent(NULL,FALSE,FALSE,NULL);中的CreateEvent的第2个参数改为TRUE试试
基本上这是最后一招了!
假设m_list中还剩一个元素时,同时有两个线程要Dequeue, 这时两个线程均不会执
if (m_List.IsEmpty()){}中的代码
而直接跳至type = m_List.RemoveHead();
MsgWaitForMultipleObjectsEx
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);
}
}
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事件对调一下