第一个多线程程序+对象和句柄的区别+感悟

先编写了一个程序,速度太慢。因此决定用多线程来提供速度,前期看了一些资料,感觉挺简单的。于是想自己先试一下,用了一个很小的Case!结果调试了一天才有结果,郁闷啊。只不过还是要把过程总结一下,也算是对自己的鞭策吧!

这次编写的程序很简单,就是个自动获得系统时间的函数。这里开了一个线程用于不断的去获取系统时间,在在对话框中显示出来。这里线程函数用的是静态成员函数,代码如下:

void CTestDlg::OnBnClickedOk()
{
	// TODO: Add your control notification handler code here

	HWND hDlg;
	hDlg=::FindWindow(NULL,"对话框");
	if(!hDlg)
		AfxMessageBox("sorry!");
	CTestDlg *pDlg = (CTestDlg *)CWnd::FromHandle(hDlg);

	AfxBeginThread((AFX_THREADPROC)CTestDlg::ThreadFun1,pDlg);

	GetDlgItem(IDOK)->EnableWindow(FALSE);
	GetDlgItem(IDCANCEL)->EnableWindow(TRUE);

}

这个函数式当点击OK时,开启多线程函数获取系统时间。其中多线程的函数如下:

DWORD WINAPI CTestDlg::ThreadFun1(LPVOID lpPara)
{
	 	CTestDlg *pDlg=(CTestDlg*)lpPara;
		pDlg->m_bRun=TRUE;

		CTime time;
		CString strTime;

	 	while (pDlg->m_bRun)
	 	{
	 		time=CTime::GetCurrentTime();
	 		strTime=time.Format("%H:%M:%S");
	 		pDlg->SetDlgItemText(IDC_TIME,strTime);
	 		pDlg->UpdateWindow();
	 		Sleep(1000);
	 	}
	 	return 0;

}

后面为了程序完整,加了个cancel函数:

void CTestDlg::OnBnClickedOk()
{
	// TODO: Add your control notification handler code here

	HWND hDlg;
	hDlg=::FindWindow(NULL,"对话框");
	if(!hDlg)
		AfxMessageBox("sorry!");
	CTestDlg *pDlg = (CTestDlg *)CWnd::FromHandle(hDlg);

	AfxBeginThread((AFX_THREADPROC)CTestDlg::ThreadFun1,pDlg);

	GetDlgItem(IDOK)->EnableWindow(FALSE);
	GetDlgItem(IDCANCEL)->EnableWindow(TRUE);

}

这就是自己所用的函数。那么自己出问题是在那个地方呢?

第一:在对ThreadFun1传递参数的时候出现问题;

第二:在ThreadFun1中调用SetDlgText出现问题。


先说第一个。自己先定义了一个CTestDlg对象,把这个对象的指针传给ThreadFun1,。其实现在看看,这里是显然不对的。因为当时在菜单栏中是调用DoModal进行调用对话框,所以对怎么得到DoModal函数调用的对话框很不了解,于是自己就想当然的自己定义另一个CTestDlg对象,用着参数。其实这个一分析,很明显的错误。因为,两种都没有逻辑上的联系,怎么可能对呢?

还尝试过把窗口句柄做为参数传给线程函数,这里主要是没有理解到窗口句柄和窗口对象的区别。于是到网上查了一下,结果如下:

从语法结构上看:

窗口句柄是Windows里的概念,因为是用C写的,所以Windows里面的窗口都是用C的struct写的(不是Cpp的 Struct)。仅仅是一些窗口属性的描述而已。那怎么标识这个窗口呢?通过指针可以标识,但是MS把指针封装了一下成了句柄,隐藏了实现细节。
  而MFC里面的CWnd概念呢,是C++的类,一个CWnd的对象就对应了一个窗口,CWnd里面封装了一个成员叫m_hWnd,这个就是他对应的窗口句柄,这个变量相当于一系列描述窗口属性成员变量,此外还封装了一些针对这个窗口句柄的一些操作。
  Windows SDK通过操作API函数来控制HWND,但是这些操作都是全局函数,没有CPP一样把这些操作封装到类里面。而MFC 就是把这些API的操作封装到了CWnd类里面。


从逻辑关系上看:
MFC中的对象,比如应用程序对象,视图对象等,是对象就会占用内存空间,我们就可以用指针指向此对象进行访问,但windows还提供了句柄访问,初看好像有点多余,实则不然。如果我们一个进程想访问另一个进程,根据对象指针访问就不行了。我们现在的Windows是一个完全保护的系统,应用程序工作于CPU的保护模式下,引入了虚存技术。每个进程拥有独立的4GB的地址空间,所以在应用程序中的地址是自己眼中的地址,不具有通用性。
那么两个进程就不能简单地传个地址就行了,窗体句柄就是windows内核的一种数据结构,不同窗体(可以是不同进程的不同窗体)有不同的窗体句柄,windows通过句柄可以识别不同的窗体对象(对应前面的全局函数)。


自己总结一下:
类的对象是类的实例化,而类的指针也相当于对类的实例化。但是因为类的封闭性(保护隐私),类和类之间的交换是不允许的。在Windows里面,为了实现类与类的交换,定义了全局的句柄,这个句柄是封装的,是相当于对象指针的。但是其和对象指针的作用完全不同。对象指针是对类的实例化,是为了对对象进行操作或者处理而定义的。句柄是为了类与类的交互而定义的,所以其不具有操作具体对象的功能,必须转换成类的对象或者对象指针。总之,他们两个的差别,从设计他们的出发点就已经决定了。


第二个是自己在调用SetDlgText的时候,用的是窗口句柄,这时候显示不出来。后面到网上搜了一下,也查了MSDN,这里应该用类的对象。而且基于以上对对象和句柄的了解,对这种认识更加深刻了。


最后,最重要的,总结一下自己的毛病。因为每次对于一件事情,完成主体花一半时间,完成其他的又花一半时间。经过几次实践,终于发现自己的毛病。在攻克主体的时候,自己会查很多资料,踏踏实实的把每条东西都理顺,所以相对来说还算比较快。但是对于主体以外的”虾兵蟹将“,总是以解决为第一目标,这个是没有错的。但是这时候就想到解决问题,没有分析问题。所以一直都这样碰得头破血流,不但花了时间还让自己很不爽。

昨天晚上看了《寒战》,这个电影给自己最深刻的印象就是:在关键时刻遇到问题更加要保持冷静,停下来认真分析一下问题,不要被问题的外表所激怒,而进入别人的主宰区。当劫犯要求赎金从九千多万到三千多万的时候,让其用半个小时从新整理。其实这就是一种在高压状态下的反应,聪明的刘sir也被问题的表面所迷惑。如果正常情况下的话,这个故事马上就可以收尾的,就不用后面这么麻烦的事情。最后刘Sir的绝地反击只是运气而已,如果劫匪不是警局内部人员,不是一切都晚了么?

其实这个和上面直接提到的是一样,在出现问题的时候,才是关键点的时候。这时候更加应该冷静,针对问题,仔细分析原因。从根本上截断产生问题的根源,而不是被问题所主导!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值