见如下代码
也可以接上帖看回顾
http://topic.csdn.net/u/20090514/17/e80f374b-24ff-4039-8dc2-0ac8180404bc.html?seed=769664972有问题,就是服务器异常断开,再正常开启后(我这里的客户端不关闭)
发送不成功时,关闭不了线程,while里一直做循环,界面出现假死状态_endthreadex(1);//关闭此线程也没有用 
return 0;//返回没有用 
发送错误时,就是关闭此线程, 
if(closethread) 
TerminateThread(hThread,0);//加了强制关闭怎么还是不行呢? 
closethread=false; 
m_hEvent=CreateEvent(NULL,TRUE,FALSE,"socketdll");//在这句前面加了三行,判断还是没有用, int OpenSocket(CString SerAddress,int SerPort,CString SendData)
{
if (m_hEvent)
{
WaitForSingleObject(m_hEvent,INFINITE);
ResetEvent(m_hEvent);
}
SendDataBuf=SendData; DWORD AIExitCode;
if(hThread && !closethread)
{
GetExitCodeThread(hThread,&AIExitCode);
if(AIExitCode==STILL_ACTIVE)
{
PostThreadMessage(ThreadID,WM_USERMSG,0,(LPARAM)&SendDataBuf);
return 1;
}
CloseHandle(hThread);
}
else
{
if(closethread)
TerminateThread(hThread,0);//这里的强制退出也没有用
closethread=false;
m_hEvent=CreateEvent(NULL,TRUE,FALSE,"socketdll");
hThread = (HANDLE)_beginthreadex(NULL,0,NewThread,0,0,&ThreadID);
if(hThread == 0)
{
CloseHandle(m_hEvent);
return 0;
}
Sleep(1);
PostThreadMessage(ThreadID,WM_USERMSG,0,(LPARAM)&SendDataBuf);
}
return 1;
}static unsigned WINAPI NewThread(void *arg)
{
if(SocketClose || StartEnv())
return 0; sockClient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr(QSerAddress);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(QSerPort);
if(INVALID_SOCKET == connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))
{//如果连接错误(对方IP或端口不正确),那么会阻塞20几秒才返回,暂时没有好的解决方案,可先发个ping包?
closesocket(sockClient);
WSACleanup();
return 0;
} int buflen = 0;   
setsockopt(sockClient,SOL_SOCKET,SO_SNDBUF,(const char*)&buflen,sizeof(buflen));
MSG msg;
if(!SetEvent(m_hEvent))
{
return 1;
} while (1)
{
if(GetMessage(&msg,0,0,0))
{
switch(msg.message)
{
case WM_USERMSG:
CString  *pStr = (CString*)msg.lParam;
if(0 > send(sockClient,pStr->GetBuffer(0),pStr->GetLength()+1,0))
{
Sleep(10);
if(0 > send(sockClient,pStr->GetBuffer(0),pStr->GetLength()+1,0))
{
closethread=true;//关闭标志位,好象没有用
closesocket(sockClient);
WSACleanup();
_endthreadex(1);//这里怎么退不出线程
return 0;//返回也没有用
}
}
pStr->ReleaseBuffer();
SetEvent(m_hEvent);
break;
}
}
Sleep(1000);
} closesocket(sockClient);
WSACleanup();
return 1;
}

解决方案 »

  1.   

     while (1)
    这个循环中也要检测退出event,当发现触发了,就退出while,接着线程退出...
      

  2.   

    我把while (1)
    改为while(!closethread)还是不行,界面假死
      

  3.   


    在whilie(1)
    {
       if(bFlag)
         return;
    }
    在while的循环体中判断某个标志等...当你想退出线程时设置bFlag = TRUE;
      

  4.   

    现在就是在发送失败时,返回那里死掉(从日志看出)
    if(0 > send(sockClient,pStr->GetBuffer(0),pStr->GetLength()+1,0))
    {
    //closethread=true;//关闭标志位,好象没有用
    //closesocket(sockClient);
    //WSACleanup();
    //_endthreadex(1);//这里怎么退不出线程
    return 0;//---------------------->这里的返回也没有用,就在这死掉
    }
      

  5.   

    我一直用的是3楼的方法!设置一个标记位,当想结束线程时,把该标记位设为false:注意要加琐! 
      

  6.   

    看到美女的回帖就是不同
    眼睛一亮,精神抖擞,又快快乐乐地调程序去了^&^可现在调了还是很郁闷地说
    加锁?可否给个小例子看看?还有,如果IP和端口错误,也会出现这情况(界面死了)
      

  7.   

    在whilie(1) 

      if(bFlag) 
        return; 

    这不是说的很清楚了么,就等于是一个P操作
      

  8.   

    设置标志位没有用的,因为是GetMessage,没有消息的时候不会判断标志位。应该处理一条消息,比如WM_CLOSE,收到消息之后,退出循环。只要调用PostThreadMessage(ThreadID,WM_CLOSE,0,0);就可使线程退出    while (1)
        {
            if(GetMessage(&msg,0,0,0))
            {
                if (msg.message == WM_CLOSE)
                {
                   break;
                }
                switch (msg.message)
                ///....
            }
        }  
      

  9.   

    测试了好几次
    PostThreadMessage(ThreadID,WM_CLOSE,0,0);
    这个方法不可以让线程退出................
           PostThreadMessage(ThreadID,WM_USERMSG,0,(LPARAM)&SendDataBuf);
        }
        //此处可写日志
        return 1;//返回不了,有问题,应该就是此处
    }
    ............
    这里比较奇怪,调用TerminateThread方法不行
      

  10.   

    就用标志位就可以哈
    用临界区把共用变量加锁
    在外面:
    CRITICAL_SECTION CriticalSection;
    InitializeCriticalSectionAndSpinCount(&CriticalSection, INFINITE);
    在whilie(1) 

    EnterCriticalSection(&CriticalSection);
      if(bFlag) 
        return; 
    LeaveCriticalSection(&CriticalSection);
      

  11.   

    给你看过了,是Dlg里FreeLibrary(hInst);这句话引起的,由于线程没有结束,而PostThreadMessage又是异步的,线程还没有结束,就调用了Free,而线程中有GetMessage函数,这个调用就一直不会返回。
    //dll里void CloseSocket()
    {
    SocketClose=true; //正常关闭socket
    NewThreadClose=true; PostThreadMessage(ThreadID, WM_CLOSE, 0, 0);  //加了这句
    }
    //exe里
    void CTestSocketDlg::OnButton3() 
    {
    // TODO: Add your control notification handler code here
    typedef void (*close)();
    close Closesocket;
    Closesocket=(close)GetProcAddress(hInst,"CloseSocket");
    Closesocket();
    //FreeLibrary(hInst); //注释掉
    SendCount=0;
    GetDlgItem(IDC_IPADDRESS1)->EnableWindow(true); 
    GetDlgItem(IDC_EDIT1)->EnableWindow(true);
    GetDlgItem(IDC_BUTTON1)->EnableWindow(true);
    GetDlgItem(IDC_BUTTON2)->EnableWindow(false);
    GetDlgItem(IDC_BUTTON3)->EnableWindow(false);

    }
    //其他一些地方小问题
    void writelog(const char *Wlog)
    {
    FILE *pFile;
    //strncpy(log_file,file_name1,sizeof(file_name));
    // strcat(log_patch,"log_file.log");
    pFile=fopen(log_patch,"a+");
    if(NULL==pFile)
    {
    printf("Don't writer log file!");
    //exit(-1); //第一次调试就飞在这里,退出明显不对啊,要返回
    return;
    }
    //...
    }
    BYTE Qqueue[114]={"PS000000000ES000000000ES000000000ES000000000
    ES000000000ES000000000ES000000000ES000000000ES000000000ES000000000E0D"};
    // 存放队列LPCTSTR ReturnQueue()
    {
    CString tmpqueue;
    tmpqueue.Format("%s",Qqueue);
    return tmpqueue;  //返回一个局部变量,函数执行完则释放,CSDN上见得最多的问题。要么直接返回CString对象,要么直接return (LPCSTR)Qqueue; 这个是全局变量,Free这个DLL之前不会被释放的。
    }
      

  12.   

    感谢greatws你的耐心解答现在问题焦点不是我要关闭时会出现的问题而是在正常运行状态下,对方突然断开,而我这又在不停地发消息时,出现的假死(发送失败,线程关闭不了)就是说,对方关闭后。我这在发送消息时,如果发现有错,就自动关闭此线程(丢失的消息不管)
    如果再一次发送,发现无线程,就再开线程,有线程就直接发送
      

  13.   

    请大侠们帮我看看呀,,,,稍为整理了下
    源码如下可下载
    http://www.namipan.com/d/f68d60317bdbdbd5e52fe4a3176aaceefa68f111f1280700http://www.namipan.com/d/f68d60317bdbdbd5e52fe4a3176aaceefa68f111f1280700
      

  14.   

    原因是有个if(hThread)判断,由于线程已经退出了,这个hThread不能表示线程存在与否,但是实际上代码还是按照线程存在来执行的,而OpenSocket函数有WaitForSingleObject,导致event不会被激发(event在线程中激发),所以界面一直卡死。
      

  15.   

    昨天调试你程序的时候也出现了假死,原因是因为在WaitForSingleObject(m_hEvent,INFINITE);阻塞的问题,m_hEvent还是没控制好
    我刚才试了下,断开后关闭线程只需在bool bExit=false;
    while(1&&!bExit)
    {
            //判断出断开后
         bExit = true;
    }