我自己写了一个多线程用的队列模版,在插入和取出的速度相同的情况下不出错,可是在取出速度大于插入速度的时候,就会报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;
}
};

解决方案 »

  1.   

    Debug Assertion Failed 应该有对话框弹出来。里面的内容是什么?
      

  2.   

    if (WaitForSingleObject(m_hOutEvent, INFINITE) != WAIT_OBJECT_0)
    ASSERT(FALSE);你是说这段吗?
      

  3.   

    在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);

    }
      

  4.   

    回复yangnix(yanxingli) :
    程序到哪儿我是希望程序继续执行下去,因为没有数据,即数据为空得时候,我希望线程等待!当等到有数据事件发生得时候,程序就可以继续执行下去了!所以没有用return NULL返回!
      

  5.   

    回复BoXoft() :
    报的是报Debug Assertion Failed错误!我已经知道是去了空数据的问题!我目前是想知道我的程序在DeQueue的时候哪儿出了逻辑错误!谢谢!
      

  6.   

    你把
    m_hInEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
    assert(m_hInEvent!=NULL);
    m_hOutEvent=CreateEvent(NULL,FALSE,FALSE,NULL);中的CreateEvent的第2个参数改为TRUE试试
      

  7.   

    光看一下子也看不出来呀,在debug状态下按F5运行,等到出错后按Alt+7看堆栈中显示的是哪个函数出错,双击那个函数定位到源代码中,再来分析。
      

  8.   

    用boundchecker软件查查看!
    基本上这是最后一招了!
      

  9.   

    你的线程同步有问题。
    假设m_list中还剩一个元素时,同时有两个线程要Dequeue, 这时两个线程均不会执
    if (m_List.IsEmpty()){}中的代码
    而直接跳至type = m_List.RemoveHead();
      

  10.   

    没怎么看代码,最后用个等待函数等待消息到达,建议用
    MsgWaitForMultipleObjectsEx
      

  11.   

    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);
    }
    }
      

  12.   

    忘了在else 下的LeaveCriticalSection(&m_lock);之后加个break
      

  13.   

    我完全没看懂你这两段代码的意图是什么
    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事件对调一下