MFC 多线程 控制进度条的问题

sknice 2014-09-02 10:44:57
最终的目的是,主线程执行费时操作,启动一个新的线程显示执行进度, 进度不要求准确,进度条一直在动就可以了.
网上有很多方法,我试过都不行,不知道怎么回事,他们的问题都是主线程执行完以后,进度条才开始动 .
网上的方法如下:
http://blog.csdn.net/bizhu12/article/details/6788241

进度条的进度是创建一个新的线程控制,当单击"开始"按钮时,就创建一个线程,在这个线程中控制进度条的进度,这样就可以对窗口进行其他
操作,要是没有创建一个新的线程控制进度,则整个程序需要等待进度条执行完后才能进行其他操作....

对于进度条控件关联了一个控件变量m_speed
CProgressCtrl m_speed;
DDX_Control(pDX, IDC_PROGRESS1, m_speed);

在头文件中
声明线程函数
static DWORD WINAPI ThreadSpeed(LPVOID lpParameter);
这里需要注意我为什么将线程函数声明为静态函数,后面我会讲解

声明这个句柄是用于接受创建线程时返回的句柄,可以使用这个句柄对线程控制,如挂起,唤醒以及终止等等操作
HANDLE m_ThreadSpeed;

声明的按钮函数,双击按钮由编译器自动生成的
afx_msg void OnBnClickedButton2(); //"开始"按钮函数
afx_msg void OnBnClickedButton1(); //"挂起"按钮函数
afx_msg void OnBnClickedButton3(); //"唤醒"按钮函数
afx_msg void OnBnClickedButton4(); //"终止"按钮函数

在cpp文件中
线程函数的实现

DWORD WINAPI CSpeedDlg::ThreadSpeed(LPVOID lpParameter)
{
CProgressCtrl *Speed = (CProgressCtrl*)lpParameter;

Speed->SetRange(0,100000); //设置进度条的范围
for (int i = 0; i < 100000; i++)
{
Speed->SetPos(i); //进度条的位置
}

return 0;
}

"开始"按钮函数的实现

void CSpeedDlg::OnBnClickedButton2()
{ // TODO: 在此添加控件通知处理程序代码
m_ThreadSpeed = CreateThread(0,0,ThreadSpeed,&m_speed,0,0); //创建线程
// 下面对代码是我自己添加的,模拟主线程费时操作
for (int i = 0; i < 100000; i++)
{


CClientDC dc(this);
CString str;
str.Format(_T("%d"),i);
dc.TextOutW(100,100,str);
}

}

线程挂起时进度条停止前进,当线程唤醒时进度条继续前进,当线程终止时,进度条永远不会在前进,除非再次单击"开始"按钮创建新线程进度条从新开始

//挂起线程函数
void CSpeedDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
SuspendThread(m_ThreadSpeed); //挂起线程函数,参数为线程句柄
}


//唤醒线程函数
void CSpeedDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
ResumeThread(m_ThreadSpeed); //唤醒挂起的线程
}

//终止线程函数
void CSpeedDlg::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
TerminateThread(m_ThreadSpeed,0); //终止线程

SendMessage(WM_CLOSE); //发送WM_CLOSE消息关闭窗口,退出程序
}
...全文
452 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
阿呆_ 2014-09-02
  • 打赏
  • 举报
回复
引用 4 楼 sknice 的回复:
[quote=引用 2 楼 piaobotudou 的回复:] 主线程同时也就是处理界面的线程。主线程里执行耗时操作,子线程中设置进度条位置最终只是发送更新界面消息到消息列队中,这个消息还是要主线程来处理才能绘制,所以就出现了执行完了才能绘制进度条。 最好的办法还是让子线程处理耗时操作,然后主线程处理消息绘制进度条
谢谢回复,讲的很明白,我的问题是现在有很多费时操作 ,如果都放在子线程里,改动有点大 , 有没有一种可能让子线程直接更新进度条进度, 记得以前写C# 程序的时候,设置设置了忽略线程安全,就可以让子线程直接操作界面控件, 不知道C++ 中是否可以??[/quote] 子线程控制主线程创建的进度条不可能,因为进度条的所有消息都由系统发送给主线程。所以如果希望子线程去控制进度条那么可以在子线程中创建这个进度条然后子线程中加入消息循环处理消息。为了避免和主线程窗口冲突,这个进度条可以创建到子线程建立的top window中然后覆盖到主窗口相应位置。这个子线程建立的top window还必须做一件事--定时查询主窗口位置然后跟随它移动(只能主动查询,不能跟踪主窗口消息,因为你可以认为主窗口已经陷入死循环不会响应任何消息--事实上操作系统也是这么认为的并且会生成一个ghost窗口替换你的主窗口以响应用户移动窗口之类的操作)。 综合起来考虑,最好还是将你的耗时操作放入子线程而主线程只负责更新/响应界面,否则即使可以用子线程更新部分界面,给用户的体验仍然非常糟糕,比如主窗口标题栏中会出现“未响应”等文字。
阿源是少年 2014-09-02
  • 打赏
  • 举报
回复
引用 4 楼 sknice 的回复:
[quote=引用 2 楼 piaobotudou 的回复:] 主线程同时也就是处理界面的线程。主线程里执行耗时操作,子线程中设置进度条位置最终只是发送更新界面消息到消息列队中,这个消息还是要主线程来处理才能绘制,所以就出现了执行完了才能绘制进度条。 最好的办法还是让子线程处理耗时操作,然后主线程处理消息绘制进度条
谢谢回复,讲的很明白,我的问题是现在有很多费时操作 ,如果都放在子线程里,改动有点大 , 有没有一种可能让子线程直接更新进度条进度, 记得以前写C# 程序的时候,设置设置了忽略线程安全,就可以让子线程直接操作界面控件, 不知道C++ 中是否可以??[/quote] MFC中是不可以的,至少我没用过也不知道怎么忽略线程安全,MFC界面的更新应该全靠消息
sknice 2014-09-02
  • 打赏
  • 举报
回复
引用 2 楼 piaobotudou 的回复:
主线程同时也就是处理界面的线程。主线程里执行耗时操作,子线程中设置进度条位置最终只是发送更新界面消息到消息列队中,这个消息还是要主线程来处理才能绘制,所以就出现了执行完了才能绘制进度条。 最好的办法还是让子线程处理耗时操作,然后主线程处理消息绘制进度条
谢谢回复,讲的很明白,我的问题是现在有很多费时操作 ,如果都放在子线程里,改动有点大 , 有没有一种可能让子线程直接更新进度条进度, 记得以前写C# 程序的时候,设置设置了忽略线程安全,就可以让子线程直接操作界面控件, 不知道C++ 中是否可以??
wyx100 2014-09-02
  • 打赏
  • 举报
回复
引用 2 楼 piaobotudou 的回复:
主线程同时也就是处理界面的线程。主线程里执行耗时操作,子线程中设置进度条位置最终只是发送更新界面消息到消息列队中,这个消息还是要主线程来处理才能绘制,所以就出现了执行完了才能绘制进度条。 最好的办法还是让子线程处理耗时操作,然后主线程处理消息绘制进度条
微型蚂蚁 2014-09-02
  • 打赏
  • 举报
回复
主线程同时也就是处理界面的线程。主线程里执行耗时操作,子线程中设置进度条位置最终只是发送更新界面消息到消息列队中,这个消息还是要主线程来处理才能绘制,所以就出现了执行完了才能绘制进度条。 最好的办法还是让子线程处理耗时操作,然后主线程处理消息绘制进度条
sknice 2014-09-02
  • 打赏
  • 举报
回复

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧