各位大侠帮忙看看,外部程序调用Close函数时,程序会死在ReceiveData线程的SendMessage语句上,阻塞了。而其它地方加入SendMessage则能发送成功,有的地方加入SendMessage之后,ReceiveData线程原来被阻塞的SendMessage也顺利发送了,但是其它地方的SendMessage又被阻塞了,情况比较复杂,程序也比较大,多谢各位了!!!#include "PETReconstruct.h"#include "HDInterface.h"
//#include "Parser.h"
#include "DataDistribution.h"
#include "LORHistogram.h"
#include "Sinogram.h"
#include "ReconAlgo.h"
#include <process.h> 
#include <windows.h>
#include <time.h> 
//20030
//两个线程函数及一个子函数申明
void ImageReconstruct(void *pvoid);//用于重建图像的线程
void ReceiveData(void *pvoid);//用于接收数据的进程
void Stop();
int *startTLookuptable = NULL;
int *startThetaLookuptable = NULL;
float *sinogramLookuptable = NULL;
int *startTbinArray = NULL;
float *systemMatrix = NULL;
unsigned char *LORInfoLookuptable = NULL;
int *LORIndexLookuptable = NULL;
short *decodingMapLookuptable = NULL;
float *energyLookuptable = NULL;HWND hReconWindow;
HANDLE reconstructThread;
HANDLE receiveDataThread;
int LORDataReadyNum = 0;
//-------通过导出函数配置的参数---------
int HDType = 1;
int AlgoType = 1;
char rawDataFileName[200] = {0};
char startTLookuptableName[200] = {0};
char startThetaLookuptableName[200] = {0};
char sinogramLookuptableName[200] = {0};
char startTbinArrayName[200] = {0};
char systemMatrixName[200] = {0};
char LORInfoLookuptableName[200] = {0};
char LORIndexLookuptableName[200] = {0};
char decodingMapLookuptableName[200] = {0};
char energyLookuptableName[200] = {0};
char LORHistogramFolder[200] = {0};
char saveDataFolder[200] = {0};
char LORHistogramName[100] = {0};//---------通过导出函数控制的信号--------
//int startReceive = 0;
bool isReceiveFinish;
bool isPause;
bool isContinue;
bool isStop;
bool isClose;extern "C"  _declspec(dllexport) int Initialize(HWND hCallFunWindow)
{
//----------------------------------------------------------------------------
//HDType = HDReadDataFlag;
//AlgoType = reconstructAlgorithmFlag;
//rawDataName =  rawDataFileName;
//hReconWindow = hCallFunWindow; hReconWindow = hCallFunWindow; FILE *fp; //CParser Parser;
//CLORHistogram LORHistogram; //------------修改TBin时需修改以下参数-------
         //一些列初始化操作
return 0;
}
//-----------------Start函数用于开辟ReceiveData和ImageReconstruct两个线程-----------------------------//start函数返回前,必须先安全关闭两个线程
//为防止重复调用前出现线程未关闭现象,这里首先调用stop函数确保两个线程已经安全退出。extern "C"  _declspec(dllexport) int Start()
{
Stop();
//初始化控制信号状态
isReceiveFinish = false;
isPause = false;
isContinue = true;
isStop = false;
isClose = false; FILE *fp;
CLORHistogram LORHistogram;
//-------------------------create a thread for the data receive----------------
//本线程内部需要首先检查isStart状态,如果为true开始接收数据。然后循环检查isClose状态,为true则停止接收 receiveDataThread = (HANDLE)_beginthread(ReceiveData, 0, &LORHistogram ); 
//----------------------------------------------------------------------------- //--------------------------create a thread for reconstruct---------------- reconstructThread = (HANDLE)_beginthread(ImageReconstruct, 0, &LORHistogram ); 
//-------------------------------------------------------------------------
WaitForSingleObject(receiveDataThread, INFINITE);
WaitForSingleObject(reconstructThread, INFINITE); //-----------------等待两个线程结束后返回----------------------------------
MessageBox(NULL, L"Start函数结束-PETReconstruct", L"提示",MB_OK);
return 0;
}
//--------------Stop函数暂时不导出,用于关闭receiveData线程和imageReconstruction线程--------------/
//stop函数会确保两个线程安全退出,否则stop函数不会返回void  Stop()
{
DWORD exitCode = 0;     
isStop = true;
//Stop之前两个线程可能已经退出,在此处先判断线程是否退出,如果没有退出则先等待线程退出。
exitCode=exitCode; GetExitCodeThread(receiveDataThread, &exitCode);
if (exitCode == STILL_ACTIVE)
WaitForSingleObject(receiveDataThread, INFINITE); GetExitCodeThread(reconstructThread, &exitCode);
if (exitCode == STILL_ACTIVE)
WaitForSingleObject(reconstructThread, INFINITE); isStop = false;
MessageBox(NULL, L"Stop函数结束-PETReconstruct", L"提示",MB_OK);
}/*************************************************************************************************************/extern "C"  _declspec(dllexport) void Close()
{
Stop();//Stop函数内部安全关闭两个线程 delete[]startTLookuptable;
startTLookuptable = NULL;
delete[]startThetaLookuptable;
startThetaLookuptable = NULL;
delete[]sinogramLookuptable;
sinogramLookuptable = NULL;
delete[]startTbinArray;
startTbinArray = NULL;
delete[]systemMatrix;
systemMatrix = NULL;
delete[]LORInfoLookuptable;
LORInfoLookuptable = NULL;
delete[]LORIndexLookuptable;
LORIndexLookuptable = NULL;
delete[]decodingMapLookuptable;
decodingMapLookuptable = NULL;
delete[]energyLookuptable;
energyLookuptable = NULL;
MessageBox(NULL, L"Close函数结束-PETReconstruct", L"提示",MB_OK);
}
/***************************************************************************************************************/extern "C"  _declspec(dllexport) void ReceiveFinish()
{
isReceiveFinish = true;
}
extern "C"  _declspec(dllexport) void Pause()
{
isPause = true;
isContinue = false;
}
extern "C"  _declspec(dllexport) void Continue()
{
isContinue = true;
isPause = false;
}

解决方案 »

  1.   

    /***************************************************************************************************************///本函数结束条件:读文件读到文件末尾,client端关闭socket连接,检测到stop信号,三个条件中中任意一个可结束本函数
    void ReceiveData(void *pvoid)
    {
    CLORHistogram *LORHistogram = (CLORHistogram*)pvoid;
    CHDInterface HDInterface;
    HDInterface.HDType = HDType;
    CDataDistribution DataDistribution;
    unsigned int *rawDataBuffer = NULL;
    CEventPair *EventPair = NULL;
    FILE *fp;
    char sNum[5] = {0}; int totalLen = 0;
    int len = 16000;
    int nbEventPair = 0;
    int readLen = 0;
    rawDataBuffer = new unsigned int[len];
    EventPair = new CEventPair[len]; //fp = fopen("E:\\socketData.dat","wb");
    //int totalLen = 0; HDInterface.HDType = HDType;
    if( HDInterface.HDType == 0)//read from file;
    {
    HDInterface.FileData.fileName = rawDataFileName;
    } if( HDInterface.HDType == 1)//read form socket
    {
    HDInterface.SocketData.host_port = 6000;
    } HDInterface.Initialize();
    LORDataReadyNum = 0; //Pause暂停之后,默认一个床位完毕,下一轮while(1)循环将把数据累加到一个新的LORHistogram中。
    while(1)
    {
    Sleep(200);
    //注意接收到stop信号后,ReceiveData线程将安全退出。
    if(isStop)  
    {
    SendMessage(hReconWindow, 0x02010 , 0, 0);
    delete[]rawDataBuffer;
    rawDataBuffer = NULL;
    delete[]EventPair;
    EventPair = NULL;
    HDInterface.Close();
    MessageBox(NULL, L"ReceiveData线程函数结束-PETReconstruct", L"提示",MB_OK);
    return ;
    }
    //注意按下暂停后,只可能是由内层while(1)循环跳出。按下continue后,只可能是由外部转入内部while(1)循环
    //按下暂停后,if语句之后的代码不能继续执行,否则会不停地重复保存LORHistogram;
    totalLen = 0;
    if(isContinue == false || isPause == true || isStop == true)
    continue;
    while(1)
    {
    //--------------------------------双重while循环------------------------------------
    readLen = HDInterface.ReadData(rawDataBuffer, len); //file end?
    //可以在此处保存rawData数据
    //fwrite(rawDataBuffer, sizeof(unsigned int)*readLen,1,fp); 
    nbEventPair = 0;
    DataDistribution.TempDistribution(rawDataBuffer, readLen, &EventPair[0], &nbEventPair);
    LORHistogram->GetLORHistogram(EventPair, nbEventPair);
    totalLen = totalLen + readLen; /*----------------------------------判断部分--------------------------------------*/
    //读文件,读到文件末尾后发出stop的信号。
    //注意发出stop信号后需立即退出本次循环,否则后面的isStop的判断中LORDataReadyNum还要自增一次
    if((HDInterface.HDType == 0)&&(readLen != len)) 
    {
    isStop = true;
    break;
    }   
    //socket,client端关闭socket连接 ,可能是移动床位或者扫描完成。此时应退出本循环,否则会造成socket接收阻塞
    //此时本程序发出pause信号,使程序处于待命状态,等待调用程序的信号,可能的信号是close(stop)或者pause
    //如果是扫描完毕,则调用程序应发出close信号
    //如果是移动床位,则调用程序应发出pause信号
    //退出本层循环后,重复检测stop,continue和pause信号
    if((HDInterface.HDType == 1)&&(readLen == 0))

    //isPause = true;
    isStop = true;
    break;
    }
    //socket,接收长度大于指定长度后停止,用于接收指定个数的事件后(或者指定时间)生成图像    
    //if ((HDInterface.HDType == 1)&&(totalLen > 0))     
    //{ LORDataReadyNum ++; break;}    //socket 检查到暂停信号后(如果需要继续接收,则在此处加入检测continue信号的循环)
    //暂停的功能应该只在socket实时传输中使用,读文件时不需要暂停
    if((HDInterface.HDType == 1)&&(isPause == true)) 

    break;
    }   
    //检测到stop信号,LORDataReadyNum自增后跳出本层循环,由外层循环处理stop信号
    if(isStop)                         
    {
    break;

    }//--------------------------第一层while循环-------------------------
    /*---------------save lORHistogram to file------测试代码-------------*/
    memset(sNum, 0, sizeof(char)*5);
    memset(LORHistogramName,0,100);
    sprintf(sNum ,"%03d", LORDataReadyNum+1);
    strcat(LORHistogramName, LORHistogramFolder);
    strcat(LORHistogramName, "\\LORHistogram");
    strcat(LORHistogramName, sNum);
    strcat(LORHistogramName, ".dat");
    if((fp = fopen(LORHistogramName,"wb"))==NULL)  
    {
    throw 20021;
    }
    fwrite(LORHistogram->coincPrompt, sizeof(float),LORHistogram->nbLORInScanner,fp); 
    if(fclose(fp) != 0) 
    {
    throw 20022;
    } LORDataReadyNum ++; 
    }//------------------------------第二层while循环-----------------------
    //if(fclose(fp) != 0) throw 20022;
    }/***************************************************************************************************************///ImageReconstruction线程结束的三个条件:stop信号,reconstructedNum == LORDataReadyNum以及ReceiveData线程结束void ImageReconstruct(void *pvoid)
    {
    CLORHistogram *LORHistogram = (CLORHistogram*)pvoid;
    FILE *fp;
    DWORD exitCode = 0;   
    char sNum[5] = {0}; char sinogramName[200];
    char imageName[200];
    int reconstructedNum = 0; CSinogram sinogram;
    CReconAlgo R; while(1)
    {
    //收到stop信号且reconstructedNum==LORDataReadyNum后,等待ReceiveData线程结束 
    //本函数暂时只能从此处跳出while(1)循环,返回。
    if((isStop)&&(reconstructedNum == LORDataReadyNum))
    {
    GetExitCodeThread(receiveDataThread, &exitCode);
    if (exitCode == STILL_ACTIVE)
    WaitForSingleObject(receiveDataThread, INFINITE);
    //注意等待线程结束的间隙,线程函数内部LORDataReadyNum可能已经改变
    if(reconstructedNum == LORDataReadyNum)
    {
    MessageBox(NULL, L"ImageReconstruct函数结束!!!-PETReconstruct", L"提示",MB_OK);
    return;
    }
    }
    Sleep(200);//200ms
    //默认重建未完成状态下,不会发出stop的指令
    while(reconstructedNum < LORDataReadyNum )
    {

    sinogram.GetSinogram(*LORHistogram);
    //------------save sinogram to file------测试代码---------------
    memset(sNum, 0, sizeof(char)*5);
    memset(sinogramName,0,100);
    sprintf(sNum ,"%03d", reconstructedNum);
    strcat(sinogramName, saveDataFolder);
    strcat(sinogramName, "\\sinogram");
    strcat(sinogramName, sNum);
    strcat(sinogramName, ".dat");
    if((fp = fopen(sinogramName,"wb"))==NULL)  
    {
    throw 20023;
    }
    fwrite(sinogram.sinogram, sizeof(float),sinogram.sinoAllSlicePixels,fp); 
    if(fclose(fp) != 0) 
    {
    throw 20024;
    }
    ////------------------------------------------------------------
    //R.SetAlgoType(AlgoType);
    //R.Recon(sinogram);
    ////----------------------------------------------------------------
    //注意;即使暂停状态,调用程序仍可能会受到重建完成的消息。
    isReceiveFinish = false;
    SendMessage(hReconWindow, WM_IMAGE_READY ,(UINT)sinogram.sinogram, 0);
    //判断数据是否传输完毕
    while(1)
    {
    if(isReceiveFinish == true)
    {
    isReceiveFinish = false;
    break;
    }
    Sleep(100);
    }
    reconstructedNum++;
    //isStop = true;
    }//end of while
    }
    MessageBox(NULL, L"ImageReconstruct函数结束-PETReconstruct", L"提示",MB_OK);
    }
    extern "C"  _declspec(dllexport) void Configure(int HDTypeIn, int AlgoTypeIn, char* LookuptableFolderIn, char* rawDataFileNameIn, char* saveDataFolderIn)
    {
    HDType = HDTypeIn;
    AlgoType = AlgoTypeIn; //--------------------------------统一数据文件夹后路径-------------------------------------
    memset(startTLookuptableName, 0, 200);
    strcat(startTLookuptableName, LookuptableFolderIn);
    strcat(startTLookuptableName, "\\start_t.dat");
    memset(startThetaLookuptableName, 0, 200);
    strcat(startThetaLookuptableName, LookuptableFolderIn);
    strcat(startThetaLookuptableName, "\\start_theta.dat"); memset(sinogramLookuptableName, 0, 200);
    strcat(sinogramLookuptableName, LookuptableFolderIn);
    strcat(sinogramLookuptableName, "\\sinogramLookuptable.dat"); memset(startTbinArrayName, 0, 200);
    strcat(startTbinArrayName, LookuptableFolderIn);
    strcat(startTbinArrayName, "\\n200t280theta180nogaptbin1pixelbin1starttbin.dat");
    memset(systemMatrixName, 0, 200);
    strcat(systemMatrixName, LookuptableFolderIn);
    strcat(systemMatrixName, "\\n200t280theta180nogaptbin1pixelbin1probabilitymatrix.dat"); memset(LORInfoLookuptableName, 0, 200);
    strcat(LORInfoLookuptableName, LookuptableFolderIn);
    strcat(LORInfoLookuptableName, "\\LORInfoLookuptable.dat"); memset(LORIndexLookuptableName, 0, 200);
    strcat(LORIndexLookuptableName, LookuptableFolderIn);
    strcat(LORIndexLookuptableName, "\\LORIndexLookuptable.dat"); memset(decodingMapLookuptableName, 0, 200);
    strcat(decodingMapLookuptableName, LookuptableFolderIn);
    strcat(decodingMapLookuptableName, "\\decodingMapLookuptable.dat"); memset(energyLookuptableName, 0, 200);
    strcat(energyLookuptableName, LookuptableFolderIn);
    strcat(energyLookuptableName, "\\energyLookuptable.dat");
    memset(rawDataFileName, 0, 200);
    strcat(rawDataFileName ,rawDataFileNameIn); memset(LORHistogramFolder, 0, 200);
    strcat(LORHistogramFolder, saveDataFolderIn); memset(saveDataFolder, 0, 200);
    strcat(saveDataFolder, saveDataFolderIn);
    }
      

  2.   


    要MsgWaitForMultiobject代替WaitForSingleObject吗?
      

  3.   

    上面说换成waitformultibleodject ,还有 作者简化贴上来的能运行吗?
      

  4.   

    我把WaitForSingleObject换成循环来检测全局变量判断线程是否结束,但是SendMessage同样被阻塞在那儿了
      

  5.   

    我把WaitForSingleObject换成循环来检测全局变量判断线程是否结束,但是SendMessage同样被阻塞在那儿了