• 5482阅读
  • 3回复

多线程跑了一会不动了 [复制链接]

上一主题 下一主题
离线lzpmail
 
只看楼主 倒序阅读 楼主  发表于: 2011-03-25
各位好, 我写了一个多线程的程序, 共创建了三个线程,用QWaitCondition和QMutex来实现同步, 但程序跑了一会就在其中的一个wait(&mutex)处不动了, 请大家帮忙,是什么原因,或有没有碰到这样情况的,分享分享下, 谢了。
离线dbzhang800

只看该作者 1楼 发表于: 2011-03-27
贴你的测试代码
离线lzpmail
只看该作者 2楼 发表于: 2011-03-27
我现在把我写的三个run()函数代码列出来,请高手指点指点

void UrineThread::run()
{
    int readlen, retval, i;
    char str[TEMPDATABUFSIZE];
    fd_set rfds;
    struct timeval tv ;

    tv.tv_sec = 0;
    tv.tv_usec = 100000;

    printf("thread....\n");
    while (!stopThread)
    {
        FD_ZERO(&rfds);                           // 清空串口接收端口集
        FD_SET(fd,&rfds);                         // 设置串口接收端口集

        while(FD_ISSET(fd, &rfds))                 // 检测串口是否有读写动作
        {
            FD_ZERO(&rfds);                                          // 清空串口接收端口集  每次循环都要清空,否则不会检测到有变化
            FD_SET(fd,&rfds);                                        // 设置串口接收端口集
            retval = select(fd+1,&rfds,NULL,NULL,&tv);

            if(retval == -1)
            {
                printf("an error accured.\n");
                break;
            }
            else if(retval)                                           //retval > 0
            {
                readlen = ::read(fd, str, TEMPDATABUFSIZE);         //读取数据

                printf("readlen value: %d\n", readlen);
                printf("data Buff size : %d\n", dataBuff.size());

                for (i=0; i<readlen; ++i)
                {
                    mutex.lock();
                    while (dataBuff.size() >= DATABUFFSIZE)
                        buffFull.wait(&mutex);                            //等待
                    dataBuff.enqueue(str);
                    buffEmpty.wakeAll();
                    enqWait.wakeAll();                                    //唤醒所有线程
                    mutex.unlock();
                }
            /*    str[readlen] = '\0';                                    //给读取的数据加结尾符
                dataBuff.append(str); */                                   //将数据加入到缓冲区中

                FD_ZERO(&rfds);
                FD_SET(fd,&rfds);

                retval = select(fd+1,&rfds,NULL,NULL,&tv);              //判断是否还有数据

                if(!retval)                                             //如果没有数据则退出第二层循环
                {
                    break;
                }
            }
        }
        msleep(60);                                                     //无数据时,睡眠100毫秒, 新增的
    }
}

void UrineShowThread::run()
{
    bool result;
    PacketType currPack;

    while (!stopThread)
    {
        mutQue.lock();
        while (packQue.size() < 1)
            deqWait.wait(&mutQue);
        printf("data Buff size: %d, data Que size: %d\n", dataBuff.size(), packQue.size());
        currPack = packQue.dequeue();
        enqWait.wakeAll();
        buffEmpty.wakeAll();
        mutQue.unlock();

        result = sHostPackHandler[gHostPackInfo[currPack.ID].type]( currPack );

        if (FALSE == result)
        {
            printf("pack handler fault.\n");
            // the command has not been processed, add code here to process it
        }
    }
}

void UrineProcThread::run()
{
    printf("data process.\n");                          //在此处加数据处理代码

    gHostPackMan.MakePack();                            //解包,并存于包队列中
    printf("out the make pack recursive\n");
}

void  PackMan::MakePack( void )
{
    UCHAR currChar;
    BOOL  result;
                                           // repeat untill no data in receive buffer
    while (!stopThread)                    //只有当所有数据都处理后才退出
    {
        mutex.lock();
                                                  // if (dataBuff.size() < 1)
        while (dataBuff.size() < 1)
            buffEmpty.wait(&mutex);
        currChar = dataBuff.dequeue();                //从缓冲区中获得一个数据
        buffFull.wakeAll();
        mutex.unlock();

        // packet ID has been received
        if (mPackIdGot)
        {
            // current byte is a valid packet data
            if ( 0x80 <= currChar )
            {
                // be careful: data stored begin from the second byte
                mCurrPack.buffer[mCurrPackLen] = currChar;
                ++mCurrPackLen;
                --mRestByte;

                // whole packet has been received,
                if ( 0 >= mRestByte )
                {
                    result = UnpackWithCheckSum( &mCurrPack.buffer[0], mCurrPackLen );

                    if (result)            //解包成功
                    {
                        mutQue.lock();
                        while (packQue.size() >= PACKQUEUESIZE)
                            enqWait.wait(&mutQue);
                        packQue.enqueue(mCurrPack);       //把解的包放到队列中去
                        deqWait.wakeAll();
                        mutQue.unlock();
                    }
                    else
                    {
                        printf("check sum fault.\n");
//                        mErrorPack ++;
//
//                        if( NULL != gPtrView )
//                        {
//                            ::PostMessage( gPtrView->m_hWnd, WM_COMM_ERROR, mErrorPack, 0 );
//                        }
                    }
                    mPackIdGot = 0;
                }
            }
            // current byte is not a valid packet data, maybe is a packet ID,
            // unget it for further analysis
            else
            {
                // there must be a error, because current packet is not integral
                //mPacksReceived.Put(Pack_ErrPack);
//                mErrorPack ++;
//
//                if( NULL != gPtrView )
//                {
//                    ::PostMessage( gPtrView->m_hWnd, WM_COMM_ERROR, mErrorPack, 0 );
//                }
                printf("the data is fault.\n");
                mPackIdGot = 0;

                mutex.lock();
                while (dataBuff.size() >= DATABUFFSIZE)
                    buffFull.wait(&mutex);                            //等待
                 dataBuff.prepend(currChar);           //currChar 可能是一个包, 重新插入队列
                 buffEmpty.wakeAll();                                  //唤醒所有线程
                mutex.unlock();
//                mUART.mRxCharQue.Unget( );
            }
        }
        // packet ID has not been received
        else
        {
            // check whether currChar is a valid packet ID
            if ( ( mMaxPackID > currChar ) && ( 0 < mPackInfo[currChar].len ) )
            {
                // ****** >>> ****** //
                mRestByte    = mPackInfo[currChar].len - 1 ;
                mCurrPackLen = 1;
                mCurrPack.ID = currChar;
                mPackIdGot   = 1;
                printf("rest byte len: %d\n", mRestByte);

                // if this kind of packet only has an ID, a whole packet received
                if ( 0 == mRestByte )
                {
                    mutQue.lock();
                      while (packQue.size() >= PACKQUEUESIZE)
                        enqWait.wait(&mutQue);
                    packQue.enqueue(mCurrPack);       //把解的包放到队列中去
                    deqWait.wakeAll();
                    mutQue.unlock();

                    mPackIdGot = 0;
                }
            }
            // currChar is not a valid packet ID
            else
            {
                printf("fault id: %d\n", currChar);
/*                mErrorPack ++;

                if( NULL != gPtrView )
                {
                    ::PostMessage( gPtrView->m_hWnd, WM_COMM_ERROR, mErrorPack, 0 );
                }

                //  there must be a error, because current packet is not integral
                mPacksReceived.Put(Pack_UnknownPack);
                */
            }
        }
    } // while

    return;
}
离线lzpmail
只看该作者 3楼 发表于: 2011-03-27
我感觉主要是看makepack这个函数, 它里面有两把锁, 我的程序跑了一会, 但最后跑到第二个run()函数内的deqWait.wait(&mutQue)时不动了, 并且此时 dataBuff缓冲区size最大(为8192个字节), 而packQue大小为0个字节。而我当时写这段代码是想让它在第一个run()里面接收串口数据写入dataBuff里, 并且只有当dataBuff缓冲区的size大于8192时就wait(), 等待第三个run()函数(也就是makepack())来唤醒第一个run();第三个run()函数的作用是把dataBuff中数据取出来进行解包, 并且(只要取出一个数据)就唤醒第一个run(),且把已解包的数据以一个数据结构体存入dataQue中, 第二个run()的作用是从dataQue中取出数据结构体对其进行处理。 现在请高手帮我看下,问题到底出在哪, 谢了
快速回复
限100 字节
 
上一个 下一个