读一个TXT文本,有10000行数据,按行读,用一个CProgressCtrl显示读取进度。
最开始我只用主线程编程,做了一个菜单,点击这个菜单弹出文件对话框,选中要读的TXT文件,然后用
for(i=1;i<=10000,i++)循环一行一行读取这10000行数据,循环体中我用进度条的SetPos函数设置进度条的进度,按我最初
的设想,程序每循环一次会刷新一次进度条的位置,这样进度条就会一点一点往上涨,但最后我看到的结果是这样的:
一打开选中的TXT文档,界面就卡住不动,界面上的进度条当然也没有任何显示,过了20多秒数据都读完了,看到进度条很快的从0涨到100%。后来在论坛上发了个贴,很多人告诉我要再开一个线程去读取文件,于是我做了如下工作:
在主线程进入for循环读取文件的之前新建了一个线程hThread1,命令如下:
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
CloseHandle(hThread1);hThread1线程的函数Fun1Proc申明为MainFrame的友元函数,然后将主线程原来for(i=1;i<=10000,i++)循环读数据的程序都搬Fun1Proc里面,在主线程里加一个while(i<=10000)的循环体,在这个循环体里根据(i/10000)*100的值来刷新进度条的进度。可是我发现进度条的反应与每开新线程是一样的,就是中间0-20秒左右没动静,最后唰的一下从0到100%。各位大哥,数据的读取我的程序都没有问题,但是这个进度条的反应该怎么弄啊?折腾我好几天了。
最开始我只用主线程编程,做了一个菜单,点击这个菜单弹出文件对话框,选中要读的TXT文件,然后用
for(i=1;i<=10000,i++)循环一行一行读取这10000行数据,循环体中我用进度条的SetPos函数设置进度条的进度,按我最初
的设想,程序每循环一次会刷新一次进度条的位置,这样进度条就会一点一点往上涨,但最后我看到的结果是这样的:
一打开选中的TXT文档,界面就卡住不动,界面上的进度条当然也没有任何显示,过了20多秒数据都读完了,看到进度条很快的从0涨到100%。后来在论坛上发了个贴,很多人告诉我要再开一个线程去读取文件,于是我做了如下工作:
在主线程进入for循环读取文件的之前新建了一个线程hThread1,命令如下:
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
CloseHandle(hThread1);hThread1线程的函数Fun1Proc申明为MainFrame的友元函数,然后将主线程原来for(i=1;i<=10000,i++)循环读数据的程序都搬Fun1Proc里面,在主线程里加一个while(i<=10000)的循环体,在这个循环体里根据(i/10000)*100的值来刷新进度条的进度。可是我发现进度条的反应与每开新线程是一样的,就是中间0-20秒左右没动静,最后唰的一下从0到100%。各位大哥,数据的读取我的程序都没有问题,但是这个进度条的反应该怎么弄啊?折腾我好几天了。
解决方案 »
- VC2008中如何给编辑框加载位图背景
- 如何创建UNICODE文本
- Richedit的字符颜色问题,哪位大侠帮帮忙!
- 请大侠帮忙用CSocket实现一个连接服务端并向服务端发送数据/接收数据,关键是在调用Receive时,如果3秒内没有数据到达,就进行下面的操作。
- socket 10053错误
- 如何从recv接收的数据中分解出我的数据?
- 请大家推荐一个C的IDE,简单实用一点,用于win2000,winxp,要能写32的控制台程序,主要用于数值计算!谢谢
- 在SDI中的FormView建立起属性页,总是不行,大家帮忙看看!
- 怎样使List响应右键
- 在VC中,怎么样使用记时器?
- 如何显示一幅bmp?
- 'ReadString' : is not a member of 'CStdioFile'
::PostMessage(Splitter3.GetPane(0,0)->m_hWnd,0x407,0L,0L)这个函数不断发送代码为0x407的消息。
因为我这个进度条是一个叫Dlg3的类的一个成员,因此我在Dlg3类的DefWindowProc函数里响应0x407消息刷新进度条。
Dlg3这个类是我在资源管理器里编辑的一个Dialog,其基类选择的CFormView,我用Dlg3作为我一个拆分子窗口的View类,也就是说我的进度条放置在这个拆分子窗口中显示。
我还是把进入多线程后的程序贴出来吧:
主线程:
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
CloseHandle(hThread1);
hMutex=CreateMutex(NULL,FALSE,NULL);
while (line<=line_num_rut)
{
WaitForSingleObject(hMutex,INFINITE);
if ((ceil(10*line/line_num_rut))==(10*line/line_num_rut))
{
progress=ceil(100*line/line_num_rut);//算出进度条位置
::PostMessage(Splitter3.GetPane(0,0)->m_hWnd,0x407,0L,0L);//发送更新进度条消息
}
ReleaseMutex(hMutex);
}
hThread1线程函数(这个读数据的函数有些复杂,但是这不主线程啊):
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
for (line=1;line<=line_num_rut;line++)
{
WaitForSingleObject(hMutex,INFINITE);
int dot_position[10];
float c=0;
for (i=0;i<LineWidth_rut;i++)
{
fseek(fp,CurrentPosition_1+i+LineWidth_rut*(line-1),0);
fread(&a[i],1,1,fp);
d[i]=a[i]-48;
}
j=0;
for (i=0;i<LineWidth_rut;i++)
{
if (d[i]==-2)
{
dot_position[j]=i;
j=j+1;
}
}
bool label_valid=false;
int data_num=0;
int num_temp=0;
for (i=1;i<LineWidth_rut;i++)
{
if (d[i]==-16&&d[i-1]!=-16)
{
num_temp=num_temp+1;
if (num_temp==9)
{
dot_position[j]=i;
}
}
}
for (i=1;i<LineWidth_rut;i++)
{
if (d[i-1]==-16&&d[i]!=-16)
{
label_valid=true;
}
if (d[i]==-16&&d[i-1]!=-16)
{
b[data_num]=c;
label_valid=false;
data_num=data_num+1;
c=0;
}
if (label_valid==true&&d[i]!=-2)
{
if ((dot_position[data_num-1]-i)>0)
{
c=c+d[i]*pow(10,dot_position[data_num-1]-i-1);
}
if ((dot_position[data_num-1]-i)<0)
{
c=c+d[i]/pow(10,i-dot_position[data_num-1]);
}
}
}
bool label_firststr=false;
CString temp_str;
stake_num_rut[line]="";
for (i=0;i<LineWidth_rut;i++)
{
if (a[i]==32)
{
label_firststr=true;
}
if (label_firststr==false)
{
temp_str=a[i];
stake_num_rut[line]=stake_num_rut[line]+temp_str;
}
if (a[i]<128&&a[i]!=32&&i<LineWidth_rut-2)
{
data_valid_rut[line]=a[i];
}
}
leftdepth_rut[line]=b[1];
rightdepth_rut[line]=b[2];
leftdepth_rdi_rut[line]=b[3];
rightdepth_rdi_rut[line]=b[4];
wholedepth_rut[line]=b[5];
maxdepth_rut[line]=b[6];
speed_rut[line]=b[7];
distance_rut[line]=b[8];
ReleaseMutex(hMutex);
}
return 0;
}
有问题的程序就这么多
另外我又发现一个问题:
我在主线程里把::PostMessage(Splitter3.GetPane(0,0)->m_hWnd,0x407,0L,0L)这句去掉,直接用
p->m_progress.SetPos(progress)这个函数设置进度条进度,其中p是指向进度条所在类的指针,m_progress就是我的进度条,这样我就不需要在主线程里发消息去告诉Dlg3更新进度条了。
做了上述改动后,程序编译都没有问题,运行打开也没有问题,但是一读取数据的时候就报错,说afxcmn2.inl这个文件出问题了。快崩溃了,这么个小问题都不知道该怎么解决。‘组织部长’同志,实在不行你就贴一个类似的源程序给我参考下吧,就是读取TXT文件并用多线程方式显示进度的就可以。
改动后的主程序如下(进入多线程部分):
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
CloseHandle(hThread1);
while (line<=line_num_rut)
{
progress=ceil(100*line/line_num_rut);//算出进度条位置
::PostMessage(Splitter3.GetPane(0,0)->m_hWnd,0x407,0L,0L);//发送更新进度条消息
}改动后的子线程函数如下:DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
for (line=1;line<=line_num_rut;line++)
{
for (i=1;i<10000;i++)
{
progress=ceil(100*line/line_num_rut);
}
}
return 0;
}
就是这么两段程序,我连互斥对象也去掉了,结果还是一点击读文件时界面就卡住,然后进度条等到所有程序运行完了以后才唰的一下从0涨到100%;
CProgressCtrl m_pb; // 进度条控件对象
afx_msg LRESULT OnSetRange(WPARAM wParam, LPARAM lParam); // 设置进度条的范围
afx_msg LRESULT OnSetPos(WPARAM wParam, LPARAM lParam); // 设置进度条的当前位置// .CPP源文件中
#define UM_SETRANGE WM_USER+1110 // 自定义的消息,设置进度条的范围
#define UM_SETPOS WM_USER+1111 // 自定义的消息,设置进度条的位置BEGIN_MESSAGE_MAP(CXXXDlg, CDialog)
ON_MESSAGE(UM_SETRANGE, &CAGEADlg::OnSetRange)
ON_MESSAGE(UM_SETPOS, &CAGEADlg::OnSetPos)
ON_MESSAGE(UM_SETFIN, &CAGEADlg::OnSetFin)
END_MESSAGE_MAP()// 设置进度条的范围消息UM_SETRANGE的响应函数
LRESULT CXXXDlg::OnSetRange(WPARAM wParam, LPARAM lParam)
{
if(m_pb.GetSafeHwnd())
{
m_pb.SetRange32(0, (int)lParam);
}
return 0;
}// 设置进度条的当前消息UM_SETRANGE的响应函数
LRESULT CXXXDlg::OnSetPos(WPARAM wParam, LPARAM lParam)
{
if(m_pb.GetSafeHwnd())
{
m_pb.SetPos((int)lParam);
}
return 0;
}// 线程函数,读取文件数据,并显示文件读取进度信息
UINT __cdecl ThreadProc(LPVOID lParam)
{
HWND hWnd = (HWND)lParam;
try
{
CFile file;
file.Open(_T("F:\\11.txt"), CFile::modeRead);
int nLen = (int)file.GetLength();
::SendMessage(hWnd, UM_SETRANGE, 0, (LPARAM)nLen);
char buf[1] = {0};
int nIndex = 0;
while(TRUE)
{
int nRet = file.Read(buf, 1);
if(!nRet)
break;
if(nIndex++ == nLen)
break;
::SendMessage(hWnd, UM_SETPOS, 0, (LPARAM)nIndex);
}
file.Close();
}
catch (CFileException* e)
{
e->ReportError();
e->Delete();
}
return 0;
}// 启动线程函数,从文件中读取数据,并显示当前读取的进度
void CXXXDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
//OnOK();
AfxBeginThread(ThreadProc, (LPVOID)GetSafeHwnd());
}
让每读100行进度条走一个格,
while(bool condition)
{
setpos(i/100);
}
读完文件condition = false;
循环就退了
ok了