创建一个互斥量监督:主线程负责读取文件,子线程设置进度条,为什么总是主线程运行完了进度条突然100%解决思路
创建一个互斥量监督:主线程负责读取文件,子线程设置进度条,为什么总是主线程运行完了进度条突然100%
刚学习多线程编程,菜鸟一个···
程序代码如下:
.cpp文件开头定义:
CStdioFile *g_pFile = NULL;//全局的文件指针
HANDLE g_hMutex = NULL;//互斥量
主线程:
void CModel::ReadFile() //菜单工具栏按钮,读取文件
{
CString strFileName,preRowStr;
char strFile[]="txt文件(*.txt)|*.txt|所有文件(*.*)|*.*||";
CFileDialog filedlg(TRUE,NULL,NULL,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY,strFile);
if (filedlg.DoModal()==IDOK)
strFileName=filedlg.GetPathName();
else
return ;
g_pFile = new CStdioFile(strFileName,CFile::modeRead);//初始化文件指针
g_hMutex = CreateMutex(NULL,FALSE,NULL);//创建互斥量
HANDLE hThread;
DWORD ThreadID; //存放线程ID
hThread = CreateThread( NULL,0,SetProgressPosThreadProc,NULL,0,&ThreadID);
bool bIsEnd = true; //指示文件是否读取完毕
DWORD dw; //互斥量信号结果
while(1)
{
if(!g_pFile) return ;//异常判断
dw = WaitForSingleObject(g_hMutex,INFINITE);
if(dw==WAIT_OBJECT_0) //互斥量等待到信号
{
g_pFile->ReadString(preRowStr);//读取文件
if (preRowStr=="MODELEND") //文件最后一行是"MODELEND"
bIsEnd = false;
}
else if(dw==WAIT_ABANDONED)
{
return ;
}
ReleaseMutex(g_hMutex);
if(bIsEnd == false) break;
}
return;
}
子线程:
DWORD WINAPI SetProgressPosThreadProc(LPVOID lParam)
{
DWORD dPos=0; //当前文件指针的位置
DWORD dLength = 1; //文件的长度
DWORD dProssPos = 0; //计算出来的进度条的位置
DWORD dPrePos = 0; //记录前一个进度条的位置
CMainFrame* pFrame = (CMainFrame*)(AfxGetApp()->m_pMainWnd); //获取当前主窗口指针
DWORD dw;
dw = WaitForSingleObject(g_hMutex,INFINITE);//等待互斥量有信号
if(dw==WAIT_OBJECT_0) //判断互斥量是否为有信号
{
dLength = g_pFile->GetLength(); //获取文件长度
}
else //废弃的信号,说明读取文件的线程有异常
{
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,100,NULL);
return 0;
}
ReleaseMutex(g_hMutex);//释放互斥量
while(dPos < dLength)//当文件未读完时执行循环
{
dw = WaitForSingleObject(g_hMutex,INFINITE); //等待互斥量有信号
if(dw==WAIT_OBJECT_0) //等待到信号
{
dPos = g_pFile->GetPosition(); //获取当前文件指针的位置
dProssPos = DWORD(double(dPos) / dLength * 100); //计算进度条的位置
}
else //废弃的信号
{
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,100,NULL);
return 0;
}
ReleaseMutex(g_hMutex); //释放互斥量
if(dProssPos!=dPrePos) //进度条位置相同时不发送更新消息
{
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,dProssPos,NULL);
}
dPrePos = dProssPos; //当前位置变为前一位置
}
//由于计算位置时用的将double 强制转换为 DWORD 型,有可能没有计算到100
//所以需要发送一个消息将进度条位置刷新到100
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,100,NULL);
Sleep(500);
//文件读取完毕以后要对文件指针进行关闭和销毁
dw = WaitForSingleObject(g_hMutex,INFINITE);
if(dw==WAIT_OBJECT_0)
{
g_pFile->Close();
delete g_pFile;
g_pFile = NULL;
}
else //废弃的信号
{
g_pFile->Close();
delete g_pFile;
g_pFile = NULL;
}
ReleaseMutex(g_hMutex);
//恢复进度条位置
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,0,NULL);
return 0;
}
程序刚开始也是挪别人的,只不过是创建两个子线程:一个读取文件,一个负责进度条。我把读取文件放到主线程里面,为什么就不行了呢。
------解决方案--------------------
g_hMutex = CreateMutex(NULL,FALSE,NULL);//创建互斥量 这个你放到外面去试一试
------解决方案--------------------
加些打印信息,看看子线程有没有进入过更新进度条的代码。
话说,这功能做成多线程干什么?
g_pFile->ReadString(preRowStr);后更新进度条不就行了?
------解决方案--------------------
ReadString后直接去设置进度条不就行了吗?
刚学习多线程编程,菜鸟一个···
程序代码如下:
.cpp文件开头定义:
CStdioFile *g_pFile = NULL;//全局的文件指针
HANDLE g_hMutex = NULL;//互斥量
主线程:
void CModel::ReadFile() //菜单工具栏按钮,读取文件
{
CString strFileName,preRowStr;
char strFile[]="txt文件(*.txt)|*.txt|所有文件(*.*)|*.*||";
CFileDialog filedlg(TRUE,NULL,NULL,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY,strFile);
if (filedlg.DoModal()==IDOK)
strFileName=filedlg.GetPathName();
else
return ;
g_pFile = new CStdioFile(strFileName,CFile::modeRead);//初始化文件指针
g_hMutex = CreateMutex(NULL,FALSE,NULL);//创建互斥量
HANDLE hThread;
DWORD ThreadID; //存放线程ID
hThread = CreateThread( NULL,0,SetProgressPosThreadProc,NULL,0,&ThreadID);
bool bIsEnd = true; //指示文件是否读取完毕
DWORD dw; //互斥量信号结果
while(1)
{
if(!g_pFile) return ;//异常判断
dw = WaitForSingleObject(g_hMutex,INFINITE);
if(dw==WAIT_OBJECT_0) //互斥量等待到信号
{
g_pFile->ReadString(preRowStr);//读取文件
if (preRowStr=="MODELEND") //文件最后一行是"MODELEND"
bIsEnd = false;
}
else if(dw==WAIT_ABANDONED)
{
return ;
}
ReleaseMutex(g_hMutex);
if(bIsEnd == false) break;
}
return;
}
子线程:
DWORD WINAPI SetProgressPosThreadProc(LPVOID lParam)
{
DWORD dPos=0; //当前文件指针的位置
DWORD dLength = 1; //文件的长度
DWORD dProssPos = 0; //计算出来的进度条的位置
DWORD dPrePos = 0; //记录前一个进度条的位置
CMainFrame* pFrame = (CMainFrame*)(AfxGetApp()->m_pMainWnd); //获取当前主窗口指针
DWORD dw;
dw = WaitForSingleObject(g_hMutex,INFINITE);//等待互斥量有信号
if(dw==WAIT_OBJECT_0) //判断互斥量是否为有信号
{
dLength = g_pFile->GetLength(); //获取文件长度
}
else //废弃的信号,说明读取文件的线程有异常
{
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,100,NULL);
return 0;
}
ReleaseMutex(g_hMutex);//释放互斥量
while(dPos < dLength)//当文件未读完时执行循环
{
dw = WaitForSingleObject(g_hMutex,INFINITE); //等待互斥量有信号
if(dw==WAIT_OBJECT_0) //等待到信号
{
dPos = g_pFile->GetPosition(); //获取当前文件指针的位置
dProssPos = DWORD(double(dPos) / dLength * 100); //计算进度条的位置
}
else //废弃的信号
{
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,100,NULL);
return 0;
}
ReleaseMutex(g_hMutex); //释放互斥量
if(dProssPos!=dPrePos) //进度条位置相同时不发送更新消息
{
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,dProssPos,NULL);
}
dPrePos = dProssPos; //当前位置变为前一位置
}
//由于计算位置时用的将double 强制转换为 DWORD 型,有可能没有计算到100
//所以需要发送一个消息将进度条位置刷新到100
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,100,NULL);
Sleep(500);
//文件读取完毕以后要对文件指针进行关闭和销毁
dw = WaitForSingleObject(g_hMutex,INFINITE);
if(dw==WAIT_OBJECT_0)
{
g_pFile->Close();
delete g_pFile;
g_pFile = NULL;
}
else //废弃的信号
{
g_pFile->Close();
delete g_pFile;
g_pFile = NULL;
}
ReleaseMutex(g_hMutex);
//恢复进度条位置
::SendMessage(pFrame->m_hWnd,WM_UPDATE_PROGRESS_POS,0,NULL);
return 0;
}
程序刚开始也是挪别人的,只不过是创建两个子线程:一个读取文件,一个负责进度条。我把读取文件放到主线程里面,为什么就不行了呢。
------解决方案--------------------
g_hMutex = CreateMutex(NULL,FALSE,NULL);//创建互斥量 这个你放到外面去试一试
------解决方案--------------------
加些打印信息,看看子线程有没有进入过更新进度条的代码。
话说,这功能做成多线程干什么?
g_pFile->ReadString(preRowStr);后更新进度条不就行了?
------解决方案--------------------
ReadString后直接去设置进度条不就行了吗?