
子线程中不能 *** 作主线程的控件具,体实现方法见上个提问,另外,UpdateData不要在子线程中用会卡的!
以下是我搜集的MFC多线程应注意的事项,很乱但很有用:
--------------------------------------------------------------------------------
MFC多线程编程注意事项 -
--------------------------------------------------------------------------------
关于启动线程时传输窗口对象(指针?句柄?)的问题:
在选择菜单中的开始线程后:
void cmainframe::onmenu_start()
{
afxbeginthread(mythread, this);
}
线程函数如下:
uint mythread(lpvoid pparam)
{
cmainframe pmainfrm = (cmainframe )pparam;
}
问题一:
这样的代码是不是有问题?
(文档中说线程间不能直接传输mfc对象的指针,应该通过传输句柄实现)
问题二:
这样使用开始好像没有问题,直接通过pmainfrm访问窗口中的view都正常。
但发现访问状态条时:
pmainfrm->m_wndstatusbarsetpanetext(2, "test);
出现debug assertion failed!(在窗口线程中没有问题)
位置是wincorecpp中的
assert((p = pmap->lookuppermanent(m_hwnd)) != null ||
(p = pmap->lookuptemporary(m_hwnd)) != null);
为什么访问view能正常,但访问状态条时不可以呢?
问题三:
如果通过传输句柄实现,怎样做呢?
我用下面的代码执行时有问题:
void cmainframe::onmenu_start()
{
hwnd hwnd = getsafehwnd();
afxbeginthread(mythread, hwnd);
}
uint mythread(lpvoid pparam)
{
cmainframe pmainfrm = (cmainframe )(cwnd::fromhandle((hwnd)pparam));
}
执行时通过线程中得到pmainfrm,访问其成员时不正常。
网友:hewwatt
大致原因解释如下:
1 mfc的大多数类不是线程安全的,cwnd及其消息路由是其中之最
2 mfc界面类的大多数方法,最后都是通过sendmessage实现的,而消息处理的
过程中会引发其他消息的发送及处理。如果消息处理函数本身不是线程安全的
你从工作线程中调用这些方法迟早会同你界面线程的用户消息响应发生冲突
3 cxxxx::fromhandle会根据调用者所在线程查表,如果查不到用户创建的cxxxx
对应对象,它会创建一个临时对象出来。由于你在工作线程中调用该方法,当然不可能查到界面主线程中你所建立起来的那个对象了。这时mfc会你创建一个临时对象并返回给你,你根本不可能期望它的成员变量会是有意义的。
所以要用也只能用cwnd::fromhandle,因为它只包含一个m_hwnd成员。 不过,要记住
跨线程直接或间接地调用::sendmessage,通常都是行为不可预测的。
1工作线程给主线程发消息使用的是SendMessage和PoseMessage函数。这两个函数的区别在于SendMessage函数是阻塞方式,而PoseMessage函数是非阻塞方式。如果不是严格要求工作线程与主线程必须同步执行,则推荐使用PoseMessage。
2不要在线程函数体内 *** 作MFC控件,因为每个线程都有自己的线程模块状态映射表,在一个线程中 *** 作另一个线程中创建的MFC对象,会带来意想不到的问题。更不要在线程函数里,直接调用UpdataData()函数更新用户界面,这会导致程序直接crash。而应该通过发送消息给主线程的方式,在主线程的消息响应函数里 *** 作控件。
3在主线程中不要使用WaitForSingleObject和WaitForMultipleObjects两个函数等待线程退出,其原因就是有导致程序死锁的隐患,特别是线程函数里调用了SendMessage或是直接 *** 作了MFC对象,更易出现此种现象。为解决这一问题,微软特提供了一个函数,MsgWaitForMultipleObjects。
照着网上的例子,写了在主线程中等待单个线程退出的程序:
DWORD dRet=-2;
MSG msg;
BOOL bWaitAll=FALSE;
int nWaitCount=2; //初始等待的线程数目
while (1)
{
dRet=MsgWaitForMultipleObjects(1,句柄的指 针,bWaitAll,INFINITE,QS_ALLINPUT);
if (dRet == WAIT_OBJECT_0 + 1)
{
TRACE("收到消息,函数返回值为%d \n",dRet);
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if (dRet == WAIT_OBJECT_0 )
{
TRACE("线程退出了\n");
break;
}
}//end while
}
实际使用中,在主线程中使用WaitForMultipleObjects导致界面线程在子线程结束前失去响应,而使用MsgWaitForMultipleObjects则很好的解决了这个问题。
本文来自CSDN博客,转载请标明出处:>
1首先在OCX的cpp文件中声明一个全局变量:
static HHOOK hHook=NULL;
2定义hHook处理函数:
LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));//模块切换时的状态保护指向当前模块状态
LPMSG lpMsg = (LPMSG) lParam;
if( (nCode >= 0) && (PM_REMOVE == wParam) &&
AfxGetApp()->PreTranslateMessage(lpMsg))
{
lpMsg->message = WM_NULL;
lpMsg->lParam = 0L;
lpMsg->wParam = 0;
void CHCOCX5Ctrl::OnMoving(UINT fwSide, LPRECT pRect)
{
COleControl::OnMoving(fwSide, pRect);
// TODO: 在此处添加消息处理程序代码
if(hMainWnd!=NULL)::SendMessage(hMainWnd, WM_MOUSEMOVE, pointx, pointy);
AfxMessageBox("moving2");
}
ocx是ocx控件的扩展名,下来说说什么是ocx控件!
说说什么是OCX控件?
OCX 是对象类别扩充组件。
如果你用过Visual Basic或者Delphi一类的可视化编程工具,那么对控件这个概念一定不会陌生,就是那些工具条上的小按钮,如EditBox,Grid,ImageBox,Timer等等。每个控件都有自己的事件、方法和属性。使用了控件的编程非常容易。首先,在程序的设计阶段可以设置一些属性,如大小,位置,标题(caption)等等;在程序运行阶段,可以更改这些属性,还可以针对不同的事件,调用不同的方法来实现对该控件的控制。控件就好像一块块的积木,程序要做的事只是将这些积木搭起来。控件的最大好处是可以重复使用,甚至可以在不同的编程语言之间使用,例如你可以在VB中嵌入用VC开发的控件。
控件的本质是微软公司的对象链接和嵌入(OLE)标准。由于它充分利用了面向对象的优点,使得程序效率得到了很大的提高,从而得到了广泛的应用。国外有很多公司就是专门制作各种各样控件的。控件的最早形式是以VBX的格式出现的,后来变成了OCX。由于Internet的广泛流行,微软公司推出了ActiveX技术,就是从OLE发展起来的,加入了>
调用控件的属性啊,ocx的属性会根据IDL的定义自动找get_XXX() 和 put_XXX()函数。
可以用命名管道,可以用事件通知,也可以用socket,不一定要用消息发送机制的
以上就是关于求mfc线程问题,全部的内容,包括:求mfc线程问题,、运行regsvr32 /u RICHTX32.OCX 出现错误、如何使得OCX控件能响应PreTranslateMessage消息等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)