关于登陆界面绘图出现“程序无法响应,界面全白”问题请教!

kxywn 2014-12-09 07:47:24
登陆界面时候:
MFC主线程启动时创建一个对象(登陆界面对象,对象中用线程绘图,主要功能是显示数据处理的进度)去绘图,接着再开一个线程去获取数据,用WaitForMultipleObjects等待线程完成数据处理,然后弹出主程序。

在获取数据线程没有完成时,登陆界面如果用鼠标点击就出现“程序无法响应“提示(正常的,没有问题,稍后就好了),主要问题是显示界面全白了,等获取数据线程退出时,界面又显示正常.....,求大神赐教!
...全文
149 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
kxywn 2014-12-26
  • 打赏
  • 举报
回复
谢谢各位解答
wyb1983510 2014-12-10
  • 打赏
  • 举报
回复
不建议阻塞界面线程,可以用自定义消息的形式处理!
阿源是少年 2014-12-10
  • 打赏
  • 举报
回复
不要在主线程中使用WaitForXXXObject,会阻塞主线程,你确实想在数据线程OK后再弹窗或者绘图,要使用自定义消息,数据线程处理完毕,往主线程PostMessage(),主线程接收消息后处理UI逻辑就不会卡住了
阿源是少年 2014-12-10
  • 打赏
  • 举报
回复
引用 4 楼 kxywn 的回复:
[quote=引用 2 楼 pcradio 的回复:] 不要在主线程中使用WaitForXXXObject,会阻塞主线程,你确实想在数据线程OK后再弹窗或者绘图,要使用自定义消息,数据线程处理完毕,往主线程PostMessage(),主线程接收消息后处理UI逻辑就不会卡住了
但是我必须要等待数据接收完成,然后再接着往下走,同时在接受数据时,登陆界面还要动态显示文字。怎么处理? 另外说明一下,如果这个过程中我桌面不做任何操作,能正常显示登陆图片文字,如果用鼠标点击登陆图片,图片就全白了,除非等待数据处理完成,才一切回复正常。求教啊[/quote] 解决问题关键就是不要在主线程WaitXXXObject() 你要数据处理完毕再接着做之后的事,如前所说,在线程处理完毕后PostMessage发一个自定义消息到主线程,主线程接收到这个消息后再做你接下来的事
kxywn 2014-12-10
  • 打赏
  • 举报
回复
引用 2 楼 pcradio 的回复:
不要在主线程中使用WaitForXXXObject,会阻塞主线程,你确实想在数据线程OK后再弹窗或者绘图,要使用自定义消息,数据线程处理完毕,往主线程PostMessage(),主线程接收消息后处理UI逻辑就不会卡住了
但是我必须要等待数据接收完成,然后再接着往下走,同时在接受数据时,登陆界面还要动态显示文字。怎么处理? 另外说明一下,如果这个过程中我桌面不做任何操作,能正常显示登陆图片文字,如果用鼠标点击登陆图片,图片就全白了,除非等待数据处理完成,才一切回复正常。求教啊
allenhiman 2014-12-10
  • 打赏
  • 举报
回复
你在主线程wait并且参数为infinit那肯定卡死啊 至少你得应该用个循环wait 比如每次wait 10毫秒 然后translate dispatch·一次消息
kxywn 2014-12-10
  • 打赏
  • 举报
回复
引用 9 楼 allenhiman 的回复:
我看你的架构是有问题的 一般来说 程序初始化的时候需要加载大量的数据 你有不想让程序看起来卡在那里。 那你加载数据的操作 就要放到一个线程里 然后再主线程里面domodal一个窗口 这个domodal的窗口起到暂停等待的作用。 线程办完事后 发一个消息给domodal的窗口 令其关闭。 右边都是这样搞,因为这样简单。 当然了,如果你确实无法将初始化部分放入一个线程,必须是在主线程里面分阶段初始化 那就得自己写消息循环。 不少程序的splash就是后者的情况
原先设计者做好的程序是数据不大的,现在新需求数据量大约是几十万,,所以啊,就这样了,而且底层接口又是阻塞的...
kxywn 2014-12-10
  • 打赏
  • 举报
回复
引用 10 楼 allenhiman 的回复:
这是我某个CryEdit工程的splash的代码 凑合看吧 应该能看出个3721来 总之就是开线程自己显示登陆框,自己写消息循环 那样肯定不会有任何问题,但挺麻烦的 ///////////////////////////////////////////////////////////////////////////// UINT CCryEditApp::SplashScreenThread( LPVOID pParam ) { CCryEditApp *self = (CCryEditApp*)pParam; g_splashScreenStateLock.Lock(); CStartupLogoDialog splashScreen; splashScreen.Create( CStartupLogoDialog::IDD ); splashScreen.SetVersion( self->m_pEditor->GetFileVersion() ); g_pInitializeUIInfo = &splashScreen; g_splashScreen = &splashScreen; g_splashScreenState = eSplashScreenState_Started; g_splashScreenStateLock.Unlock(); g_splashScreenStateChange.Notify(); MSG msg; while ( GetMessage( &msg, NULL, 0, 0 ) ) { g_splashScreenStateLock.Lock(); if ( g_splashScreenState == eSplashScreenState_Destroy ) { g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; g_splashScreenStateLock.Unlock(); return 0; } g_splashScreenStateLock.Unlock(); TranslateMessage( &msg ); DispatchMessage( &msg ); } g_splashScreenStateLock.Lock(); g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; g_splashScreenStateLock.Unlock(); return 0; }
很感谢这位兄台的耐心回答 现在我发现就是鼠标点击登陆界面才出现登陆界面白(提示程序无法响应,其实等一会就好了),不点击就不出现,我想我能不能屏蔽鼠标键盘输入就可以了?(我工程中登陆等待界面也是主线程中的一个对象,等待对象也是开启线程绘图的)
allenhiman 2014-12-10
  • 打赏
  • 举报
回复
这是我某个CryEdit工程的splash的代码 凑合看吧 应该能看出个3721来 总之就是开线程自己显示登陆框,自己写消息循环 那样肯定不会有任何问题,但挺麻烦的 ///////////////////////////////////////////////////////////////////////////// UINT CCryEditApp::SplashScreenThread( LPVOID pParam ) { CCryEditApp *self = (CCryEditApp*)pParam; g_splashScreenStateLock.Lock(); CStartupLogoDialog splashScreen; splashScreen.Create( CStartupLogoDialog::IDD ); splashScreen.SetVersion( self->m_pEditor->GetFileVersion() ); g_pInitializeUIInfo = &splashScreen; g_splashScreen = &splashScreen; g_splashScreenState = eSplashScreenState_Started; g_splashScreenStateLock.Unlock(); g_splashScreenStateChange.Notify(); MSG msg; while ( GetMessage( &msg, NULL, 0, 0 ) ) { g_splashScreenStateLock.Lock(); if ( g_splashScreenState == eSplashScreenState_Destroy ) { g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; g_splashScreenStateLock.Unlock(); return 0; } g_splashScreenStateLock.Unlock(); TranslateMessage( &msg ); DispatchMessage( &msg ); } g_splashScreenStateLock.Lock(); g_pInitializeUIInfo = nullptr; g_splashScreen = nullptr; g_splashScreenStateLock.Unlock(); return 0; }
allenhiman 2014-12-10
  • 打赏
  • 举报
回复
我看你的架构是有问题的 一般来说 程序初始化的时候需要加载大量的数据 你有不想让程序看起来卡在那里。 那你加载数据的操作 就要放到一个线程里 然后再主线程里面domodal一个窗口 这个domodal的窗口起到暂停等待的作用。 线程办完事后 发一个消息给domodal的窗口 令其关闭。 右边都是这样搞,因为这样简单。 当然了,如果你确实无法将初始化部分放入一个线程,必须是在主线程里面分阶段初始化 那就得自己写消息循环。 不少程序的splash就是后者的情况
kxywn 2014-12-10
  • 打赏
  • 举报
回复
引用 3 楼 allenhiman 的回复:
你在主线程wait并且参数为infinit那肯定卡死啊 至少你得应该用个循环wait 比如每次wait 10毫秒 然后translate dispatch·一次消息
我改为 while(WAIT_TIMEOUT==WaitForMultipleObjects(THREAD_NUM, m_hThrehandle, TRUE, 30)) { PeekMessage(&msg,NULL,0,0,PM_REMOVE);// TranslateMessage(&msg); DispatchMessage(&msg); }; 点击的时候的确没有在出白了。 新问题: 主线程继续运行时,界面显示对象画图正常,如果鼠标再点击登陆界面,登陆界面又白了(提示程序无法响应,其实等一会就好了),此时主线程在执行其他操作(初始化界面,初始化数据),这个是什么问题啊?
allenhiman 2014-12-10
  • 打赏
  • 举报
回复
不信老人言啊 我说的就是解决方案 这相当于在你wait的地方 domodal了一个窗口
vocanicy 2014-12-09
  • 打赏
  • 举报
回复
应该是你的主线程阻塞了,检查一下你的主线程创建完登陆界面后在做什么?

15,979

社区成员

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

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