各位大侠帮忙看看,外部程序调用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;
}
//#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;
}
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);
}
要MsgWaitForMultiobject代替WaitForSingleObject吗?