线程同步建议阅读《Windows核心编程》一书。

解决方案 »

  1.   

    用CreateSemaphore创建信号量,初始化为0,接收线程接收完数据后ReleaseSemaphore,解压缩线程用WaitForSingleObject等待信号。
      

  2.   

    不知道接收线程里怎么用recvfrom,可以将socket的指针传递作为参数传递进去,还有,接收到的数据存入filebuf中,解压线程中用到这个filebuf,这两个线程怎么同步啊?思路大概这样可以做一个全局的数据队列, 
    数据往后塞,解压从前面取,大概就那样. 具体的还有很多的路~:)
      

  3.   


    感谢各位参与
    因为要实时接收,我在接收线程里用while(1){ recvfrom()}不断接收,统计收到10包,存到buf里,解压线程里从这个buf里读,进行解压,因为解压时间长,数据很容易丢,请各位给以高见,
    我是用信号量还是事件?如果用信号量,我既然开两个线程,初值应设为2吧?
    用事件的话,收到10包,通知解压工作,数据包丢失,一次解压10包一组,会造成4组数据丢失。
      

  4.   

    Createthread(NULL,0,Receive,0,0,NULL) 要传类指针的参数吧. 并且接受线程用高优先级.
     
      

  5.   

    还有个问题
    我在菜单CSView::start()消息函数里同时开辟接收,解压,保存线程,合适么?
    还是在CSView::OnInitialUpdate()中创建线程啊?
      

  6.   

    因为我听说菜单消息函数执行完,相当于主线程结束了,容易造成死锁,是么?
    用创建完线程,加waitforsingobject()么?
      

  7.   

    信号量的意思是有多少个解压任务,跟线程数没什么关系的,如你接收到一个数据包就可以给解压线程解压的话,那么就ReleaseSemaphore,让任务队列中多一个数据包解压任务。而解压线程WaitForSingleObject返回的话,信号量减一,并且拿一个数据包开始解压任务,任务队列中相应减少一个任务。
    消息函数执行完主线程不会结束的,不是有个消息循环在那么?除非你发了让应用程序退出消息循环的消息。
    同时,主线程退出前保证所有子线程结束。
    以上是我的理解
      

  8.   

    服务器不停的发包,客护断在接收线程里采用WSAASYNCSELECT接收数据,一包512字节,采用这样的话,点击菜单项,容易造成包丢失,
    我现在是接受线程里用用while(1){ recvfrom()}不断接收,容易阻塞,造成数据丢失
    我的接受线程,具体怎么作好?
      

  9.   

    MFC 的CAsyncSocket(异步)和CSocket(同步) 本身有 Receive、Send等函数,其实本身就是线程,你可以直接用,不需要自己再创建线程了
      

  10.   

    我是接受到10包,释放信号量,进行解压一次,
    直接在一个线程里同时接收,保存,解压,不行,服务器每隔20ms发10包数据,我的解压时间太长,解压10包用40ms,怎么解决?请高手帮忙提供好建议,最好哪位作过这方面,提供相关代码[email protected]
      

  11.   

    大侠们,我实现的传输是多路的,当我再加一路的话,当然两路分别进行解压,我如果把两路放到一个线程里,两路按顺序解压,时间很长,数据丢的多,是不再加一线程,实现另一路解压, 思路如下:
    PtransView.cpp 
    CSemaphore  m_Semaphore(2, 3, NULL);
    bind();

    UINT ReceiveProc(LPVOID lpParameter)
      {
        recvfrom();//每包放到Codebuf,20包时即count==20,写数据到解压buf中,
       if(count==20)     
        {   m_Semaphore.Lock();
            CopyMemory(Codebuf_A, Codebuf, 11250);  //A 路数据
            CopyMemory(Codebuf_B, Codebuf+11250, 11250);B 路数据
            m_Semaphore.Unlock();
        }
    }
    UINT DeprocessProc1(LPVOID lpParameter)
    {
            m_Semaphore.Lock();
    CopyMemory(Picbuf_A,Codebuf_A,11250);
    m_Semaphore.Unlock();
           deprocess(Picbuf_A  );解压}
    UINT DeprocessProc2(LPVOID lpParameter)
    {
            m_Semaphore.Lock();
    CopyMemory(Picbuf_B,Codebuf_B,11250);
    m_Semaphore.Unlock();
            deprocess(Picbuf_B  );
    }
    请提出高见,并指出其中毛病? bind 后,加select函数么,因为只用recvfrom,数据阻塞丢失?
      

  12.   

    是应该用两个信号量吧,写入Codebuf_A和读取Codebuf_A 两个操作,不能让他有同时的机会
      

  13.   

    两个信号量也不行阿 ,请大侠们指点改改,代码更改如下:
    PtransView.cpp  
    CSemaphore  m_Semaphore1(1, 2, NULL); 
    CSemaphore  m_Semaphore2(1, 2, NULL); 
    bind(); UINT ReceiveProc(LPVOID lpParameter) 
      { 
        recvfrom();//每包放到Codebuf,20包时即count==20,写数据到解压buf中, 
       if(count==20)      
        {  
            m_Semaphore1.Lock(); 
            CopyMemory(Codebuf_A, Codebuf, 11250);  //A 路数据    
             m_Semaphore1.Unlock(); 
           
            m_Semaphore2.Lock(); 
            CopyMemory(Codebuf_B, Codebuf+11250, 11250);B 路数据 
            m_Semaphore2.Unlock(); 
        } 

    UINT DeprocessProc1(LPVOID lpParameter) 

            m_Semaphore1.Lock(); 
            CopyMemory(Picbuf_A,Codebuf_A,11250); 
            m_Semaphore1.Unlock(); 
           deprocess(Picbuf_A  );解压 } 
    UINT DeprocessProc2(LPVOID lpParameter) 

            m_Semaphore2.Lock(); 
            CopyMemory(Picbuf_B,Codebuf_B,11250); 
            m_Semaphore2.Unlock(); 
            deprocess(Picbuf_B  ); 

      

  14.   

    楼上大侠们,请教新问题
    大侠,我只判断接收线程数据情况,发现周期性的丢15场数据,请大伙帮看看我得接收线程有什么毛病,代码如下:Bind();
    CWinThread*testthread=AfxBeginThread(RecvProc,(LPVOID)pRecvParam,THREAD_PRIORITY_NORMAL,0,0,NULL);UINT ReceiveProc(LPVOID lpParameter)
    {   
    SOCKET m_sRecv = ((RECVPARAM*)lpParameter)->sockR;
    HWND    m_hWnd     = ((RECVPARAM*)lpParameter)->hwnd; 
    delete lpParameter; //视频讲述时,遗忘了释放内存的操作。sunxin char chANS[16];
    SOCKADDR_IN m_RemoteAddr;
    int iAddrSize; 
    iAddrSize = sizeof(m_RemoteAddr);
    int iRecievedNum=0;
    _int32 temp;
    _int32 temp0;
    char chRecv[BLOCK];
    char tempData[BLOCK];//514
        while(1)
    {
    iRecievedNum=recvfrom(m_sRecv,chRecv,BLOCK,0,(LPSOCKADDR)&m_RemoteAddr,&tmp);
    if(iRecievedNum == SOCKET_ERROR)
    {
    //         ReportWinsockErr("Could not Receive the Data.");
        return 0L;
    }
        else
    {
             memcpy(tempData, chRecv, iRecievedNum);/////////////////////////end 为服务器发完10包就是1场数据的标志器接收线程不停的接收存
                if(tempData[0] == 'E' && tempData[1] == 'N' && tempData[2] =='D')
            {   
                 CFile file;
                    file.Open("videoJ.2C",CFile::modeReadWrite | CFile::typeBinary  );
                   file.Seek( 0L, CFile::end );
                   file.Write(Codebuf,1052);
                   file.Close();    

    // m_Semaphore.Lock();

    // memcpy(showbuf, Codebuf, 11264);
    // critical_section.Unlock();
    // m_Semaphore.Unlock();
     
              }
     
             else if (iRecievedNum != BLOCK ) // now:BLOCK=1052
    {
              AfxMessageBox("The data is wrong !");
    //          ReportWinsockErr("The data is wrong !");
     return 0L;
    }
             else if (iRecievedNum == BLOCK )/////////////收每包数据,line为=为每包标号
           {
    UINT line = ((tempData[0] << 8) & 0x0000ff00) + (tempData[1] & 0x000000ff);
    char data,data0;
    if (line < 0 || line >= 10)      
    {
    line = 0;
                            
    }

    temp=1052*line;

    for (  int i = 0, j = 0;i < 1052; i++, j++)
    {
    data = tempData[j+2];
    *(databuff+i+temp) = data;
    }      



    } }
      return 0; 
    }
      

  15.   

    UDP协议经常发生丢包现象,要自己设计应答和重发机制。
    tempData[j+2];会越界。
      

  16.   

    针对楼主:我只判断接收线程数据情况,发现周期性的丢15场数据,请大伙帮看看我得接收线程有什么毛病 
    接收线程recvfrom好象有点问题
    我有相关代码,发到你的邮箱里
      

  17.   

    感谢楼上代码
    各位,大侠,我的接收线程还是不行啊
    我用另外2种非阻塞方法
    如下selsctIO,wssaaeventselect也不行哪位高手指点阿郁闷阿 好答案帖子多加分 
      

  18.   

    看这个问题讨论这么多,总结起来还是搂主基础差,不理解。
    我归纳一下:首先你接收数据肯定得用一个线程,解压数据用一个线程。而你接收的数据缓冲区和解压数据缓冲区要分开,当接收到一定数据量时通知解压线程,这个可以通过信号量(事件)来做到;解压线程访问接收数据缓冲区,这个时候需要用临界区对这个数据缓冲区进行保护(接收线程读写也用这个临界区保护),将数据拷贝到自己的数据区,释放临界区,这样接收和解压就可以同时进行,因为是不同的两块数据,不会冲突。如果接收太快,来不及解压,可以考虑再开解压线程,直到一个平衡点;这个平衡点还可能造成数据丢失,那就是传输的极限了,只有在发送方进行限制。
    楼主还提到菜单消息和接收线程之间存在干扰,这就不应该了,不知道你是怎么设计的。菜单消息属于界面线程,应该和接收不是一个线程,互相之间不会影响。我怀疑你把WSAAsyncSelect的回传消息设置成和Windows自身的消息值一样了,要避免。可以用注册消息的方式完全避开消息号冲突。
      

  19.   

    我现在的问题是,只运行接受线程测试,其他线程都屏蔽,也会偶尔丢16场(每场10包),selsctIO,wssaaeventselect模式都用过了,也不行,请问是怎么回事?