最近用opencv+mfc做了一个简单的程序(点击button后,打开视频,另一个button关闭视频)。问题来了,读视频的程序是个死循环。怎么解。因此,应该考虑线程的问题了。让视频程序在线程里跑。
何为线程?
线程如何实现?
实际上可以这样简单的理解线程,它是CPU的调度单位.而一个线程是对应一个函数.所以别把一个线程想得太复杂,就只是执行个函数而已.只不过执行的时候是并行执行罢了.如果只是简单的几个线程不涉及使用共同的资源,没其他啥关联.就完全跟简单的执行一个函数类似.只是如果多个线程间关系复杂就会涉及到啥同步问题,那样就有很多复杂的细节性问题.
线程与函数
线程函数必须是全局函数,或者是类的静态成员函数,因为非静态成员函数有this指针,而在进程中无法访问此指针。
但是静态成员函数只能访问静态成员,解决此问题途径:
1. 就是在调用静态成员函数时将this指针作为参数传入,通过该指针访问非静态成员。
2. 不将线程函数定义为类的静态成员函数,而是定义为类的友元函数,这样函数线程也可以有类成员函数相同的权限。
开始有摄像头打开函数:
bool CcamShowDlg::CameraOpen()
{
if (capture.isOpened() == 0)
{
AfxMessageBox(_T("摄像头初始化失败"));
return false;
}
while (1)
{
Mat frame;
capture >> frame;
imshow("VideoShow",frame);
waitKey(30);
}
return false;
}
若直接在clickbutton下添加函数
void CcamShowDlg::OnBnClickedButtonCameraopen()
{
// TODO: 在此添加控件通知处理程序代码
CameraOpen();
}
点击button后程序进入了CameraOpen()的死循环。
因此创建一个线程函数来调用CameraOpen()。
void CcamShowDlg::OnBnClickedButtonCameraopen()
{
// TODO: 在此添加控件通知处理程序代码
CWinThread* pThread;
pThread = AfxBeginThread(ThreadFunc,NULL);
}
UINT CcamShowDlg::ThreadFunc(LPVOID lpParam)
{
CameraOpen();
return 0;
}
此时的CameraOpen()必须是类的静态成员函数
static bool CameraOpen();
若CameraOpen()不是静态成员函数。此时程序应变为:
UINT CcamShowDlg::ThreadFunc(LPVOID lpParam)
{
CcamShowDlg *pObj = (CcamShowDlg *)lpParam;
pObj->CameraOpen();
return 0;
}
void CcamShowDlg::OnBnClickedButtonCameraopen()
{
// TODO: 在此添加控件通知处理程序代码
CWinThread* pThread;
pThread = AfxBeginThread(ThreadFunc,this);
}
友元函数
友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。通常同一个开发者会出于技术和非技术的原因,控制类的友元和成员函数(否则当你想更新你的类时,还要征得其它部分的拥有者的同意)。
形式
friend 类型名 友元函数名(形参表);
然后在类体外对友元函数进行定义,定义的格式和普通函数相同,但可以通过对象作为参数直接访问对象的私有成员
说明如下:
1)必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数的函数原型,友元函数的说明可以出现在类的任何地方,包括在private和public部分;
2)注意友元函数不是类的成员函数,所以友元函数的实现和普通函数一样,在实现时不用"::"指示属于哪个类,只有成员函数才使用"::"作用域符号;
3)友元函数不能直接访问类的成员,只能访问对象成员,
4)友元函数可以访问对象的私有成员,但普通函数不行;
5)调用友元函数时,在实际参数中需要指出要访问的对象,
6)类与类之间的友元关系不能继承。
7)一个类的成员函数也可以作为另一个类的友元,但必须先定义这个类。
用法参见http://blog.csdn.net/insistgogo/article/details/6608672