COM *** 作,它有一套自己关于跨线程和跨进程的模型,这是个复合模型,会衍生出大约7,8种组合。学习COM,这个是一定要吃透的。楼主阅读一下关于CoInitializeEx函数的帮助文档,能多多少少体会到一些。但如果没学习过COM,光看MSDN的帮助文档,如坠云里雾里一般,很难理解的。因此,建议买本COM的书,稍微参阅一下,其次网上譬如CSDN中有很多热心人写的关于线程进程有关的COM模型,和使用规则,优缺点,可以拜读一下!
在MFC中,可能不太会形成跨线程传递变量的危害性,这种观念吧。所以,在MFC中,似乎我们能随心所欲在线程之间传递变量,但其实是不对的,典型的就是主线程创建的窗口和控件,最好不要在其它线程中直接 *** 纵,而是通过线程间通信的方法,让创建窗口和控件的主线程来 *** 纵窗口和控件。
因此,变量是不能乱传地,到了COM中,这个限制是非常明显的,COM中有概念叫MARSHAL、PROXY、STUB,当然它主要是进程相关的概念,同样说明了,非线程自己创建的东西,不是该线程使用就会有问题。
像VIEW这种界面的东西不要随便乱传给工作线程这种非界面线程。
我的建议是:
建工作线程,因为数据库 *** 作及从数据库反馈到程序级的数据需要进行再加工,这些步骤都可能会非常耗时,耗时 *** 作放在界面线程,会使界面线程无法处理WM_XXX的消息,造成界面假死。因此,像智能指针这种东西放到工作线程里进行独立管理,工作线程通过智能指针向数据库要数据,然后处理,存放数据结果到程序中约定的地方,如全局变量,虚拟内存等地方。数据处理完,通过自定义消息,向界面线程发送自定义消息,使界面线程能够在自定义消息中,将保存的数据显示到界面中,发送线程消息有个函数就是PostThreadMessage。
其他的细微细节也可以考虑,到底是创建自己的线程,还是使用线程池等。随着经验的丰富,会考虑很多问题的,关键是理论知识要学,实践也不能没有。
最后就是概念修正, _ConnectionPtr它是一个标准的C++类,C++类可以重载-> *** 作符,这个被重载的指针 *** 作符,使得通过该类实例化的变量在实际使用时,行为更像是一个指针,而不是个普通变量,这个被重载的指针 *** 作符才是智能指针,而不是指_ConnectionPtr类是智能指针,顶多说它是个智能指针类,我也见过有翻译成灵巧指针的,英文原版是SMART POINTER。
请问阁下的意思是多个进程共享一个或者多个数据吧,这种情况下必须采用线程同步机制,下面,笔者罗列集中方式,让您看看吧。
1,关键代码区,亦称作临界区,一般应用于同一进程下不同线程的某一共享数据,
下面采用伪代码
CCriticalSection section//声明临界段
int array[10] //共享变量
Thread A: section.Lock()
array[3] = 2;
//访问, *** 作共享变量
section.Unlock()
Thread B: section.Lock()
array[0] = 3;
//访问, *** 作共享变量
section.Unlock()
int main()
{
AfxBeginThread(mythreadA,NULL)
AfxBeginThread(mythreadB,NULL)
Sleep(10000)
return 1
}
1,互斥量,一般应用于同一进程及不同进程下不同线程的某一共享数据,
handle hmutex = createMutex()
waitforsinglebject(hmutex,infinte)
releasemutex(hmutex)
handle hmutex = createMutex() //声明互斥量
int array[10] //共享变量
Thread A:
waitforsinglebject(hmutex,infinte)//等待线程调度
array[3] = 2;
//访问, *** 作共享变量
releasemutex(hmutex)//释放本处对象,恢复可调度状态
Thread B: waitforsinglebject(hmutex,infinte)//等待线程调度
array[0] = 3;
//访问, *** 作共享变量
releasemutex(hmutex)//释放本处对象,恢复可调度状态
int main()
{
AfxBeginThread(mythreadA,NULL)
AfxBeginThread(mythreadB,NULL)
Sleep(10000)
return 1
}
这个 *** 作和临界区的单独使用的 *** 作是一模一样的。
3,事件对象,用于线程间的相互唤醒。
在VC下,我们用 HANDLE g_Event=CreateEvent(...)创建一个事件对象,
CreateEvent函数中的有一个参数可以将此事件对象设置为自动重置还是人工重置。
一般在此事件对象相关的线程函数中会有这样的句子
while (TRUE)
{
WaitForSingleObject(g_Event,INFINITE);
。。。
}
就说明这个线程在等待此事件对象的信号,事件对象有两种状态,一种是有信号状态,一种是无信号状态。
当我们用函数SetEvent(g_Event)将事件对象变为有信号状态时,就是你说的事件得到通知,
这个线程的WaitForSingleObject函数就可以继续向下执行,相当于线程进入可调度状态
(本来此线程的程序是卡在这个位置的,相当于不可调度)。
而人工重置与自动重置的区别呢,重置就是将事件对象变成无信号状态,
人工重置就是使用函数ResetEvent(g_Event)将事件对象重置,
而自动重置就是等待函数调用之后事件对象自动成为无信号的,不需人工调用ResetEvent函数。
handle hevent= createevent(0, true/false, 0, 0)
waitforsigleobject(infinite)
(resetevent(hevent)在人工重置的情况下)
..........
setevent(hevent)//如果自动重置下执行一次后不再调用它,线程会一直堵塞;而人工重置不重置下这相当没有加事件对象了
4,CsingleLock,使用它是为了OOP,方便维护
1,)应用时一般用在函数内部,用做类成员有性能缺失,与CCriticalsection有区别
fun()
{
CsingleLock csingle
csingle.lock//不需要解锁了,因为CsingleLock 析构函数自动解锁,一般用在函数内部
dowork
}
5,CSemaphore 通 常 用 于 当 一 个 应 用 程 序 中 同 时 有 多 个 线 程 访 问 一 个 资 源
( 例 如, 应 用 程 序 允 许 对 同 一 个Document 有 多 个View) 的 情 况
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)