VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1855|回复: 14

我用AfxBeginThread起一线程,线程函数里需要view类指针,但是会内存泄漏或是断言错误?

[复制链接]

1

主题

9

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
发表于 2020-9-25 19:00:01 | 显示全部楼层 |阅读模式
我是一个MDI,对话框里起一线程。在对话框类的主线程按下面获得view类指针,会有内存泄漏。在另起的线程里按下面获得view类指针,会有断言错误。
CMDIFrameWnd *pMain=(CMDIFrameWnd *)AfxGetApp()->m_pMainWnd;//
CMDIChildWnd *pChild=(CMDIChildWnd *)pMain->GetActiveFrame   
CMyView *pView=(CMyView *)pChild->GetActiveView();
请教大侠帮忙!
回复

使用道具 举报

0

主题

5

帖子

6.00

积分

新手上路

Rank: 1

积分
6.00
发表于 2020-9-26 16:15:01 | 显示全部楼层
相互关系的界面应该在同一线程里创建、访问、销毁。
回复

使用道具 举报

1

主题

9

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-9-26 20:30:01 | 显示全部楼层
楼上能说的详细一点吗?
我的代码是在在view类里打开一个对话框,然后在对话框里创建线程,在线程函数里要得到当前活动的view类指针,从而给view类的成员变量添加内容,在界面上画图。这样有错误吗?
回复

使用道具 举报

0

主题

2

帖子

2.00

积分

新手上路

Rank: 1

积分
2.00
发表于 2020-9-26 20:45:01 | 显示全部楼层
通常来讲,在MFC中,跨线程是不能传递CWnd对象指针的。因为在每个线程中都有一个自己的内部map,该map记录了HWND和与之对应的CWnd对象。当一个CWnd对象被创建时,它的HWND和CWnd对象指针就会被记录到该线程中的map,但其他的线程的map没有记录。
当跨线程传递CWnd指针时,调用CWnd的某些函数时,这些函数会进行有效性检查,也就是检查map,因为map中没有相应的记录,就会报错。通常这个错误是 AsserValid(this)
所以,在MFC中跨线程传递参数,最好传递句柄HWND,而不是CWnd对象指针。
回复

使用道具 举报

1

主题

9

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-9-26 21:00:01 | 显示全部楼层
我的代码具体是这样的:
MDI
MyView是基于CFormView的
在Dialog类里面一个按钮函数
void CUsbBegin::OnButtonStart()
{
...
//创建画图显示线程
m_draw=AfxBeginThread(DrawGraph,(void *)this,THREAD_PRIORITY_BELOW_NORMAL,\
0,CREATE_SUSPENDED);
m_draw->m_bAutoDelete=false;
m_draw->ResumeThread();
...
...
CDialog::OnOK();
}

线程函数是一个全局函数:
UINT DrawGraph(LPVOID lpV)
{
CUsbBegin *pDraw=(CUsbBegin *)lpV;
pDraw->ShowDataItems();
...
       
}

UINT CUsbBegin::ShowDataItems()
{
       
CMDIFrameWnd *pMain=(CMDIFrameWnd *)AfxGetApp()->m_pMainWnd;//Get the active MDI child window.   
CMDIChildWnd *pChild=(CMDIChildWnd *)pMain->GetActiveFrame();//Get the active view attached to the active MDI child window.   
CMyView *pView=(CMyView *)pChild->GetActiveView();
pView->func();
...
...
}
执行或是debug都会出现
先是断言错误,点击确定然后是内存不能读的错误。

如果我想在画图线程里得到view类指针,从而往界面画图,应该怎么实现呢?
谢谢谢谢^_^
回复

使用道具 举报

0

主题

2

帖子

2.00

积分

新手上路

Rank: 1

积分
2.00
发表于 2020-9-26 21:15:01 | 显示全部楼层
可以这样处理:
自定义一个消息,比如WM_USER_DRAW,
当需要进行绘制操作时,就像view发送该消息,用PostMessage或者SendMessage都可以。如果需要传递数据,就用全局变量或者用SendMessage.
大致的伪代码如下:

hWnd ; // 这是创建线程时通过参数传递过来的CMyView的句柄
...
// 定义并初始化绘制操作所需的数据,theData
::SendMessage( hWnd, WM_USER_DRAW, (WPARAM)&theData, (LPARAM)NULL);
///////////////////////////////////////////////
在CMyView中添加消息相应函数,在该函数进行实际的绘制操作
LRESULT CMyView::OnUserDraw( WPARAM wParam, LPARAMlParam )
{

...
return 0L;
}


回复

使用道具 举报

1

主题

9

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-9-27 01:00:01 | 显示全部楼层
我的数据量很大,要求实时性很高,这样频繁的发送和接收消息,效率高吗?
如果我直接定义一个全局变量data,在view类里面声明一下extern data;在view类里面画图处理是不是也可以?
但是这样就不是另起一个线程函数里面画图了,是不是就相当于主线程里面画图了?
marrco:是在画图线程里面SendMessage吗?
回复

使用道具 举报

1

主题

9

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-9-27 10:00:01 | 显示全部楼层
hWnd ; // 这是创建线程时通过参数传递过来的CMyView的句柄

请教一下这条怎么实现?
回复

使用道具 举报

1

主题

9

帖子

7.00

积分

新手上路

Rank: 1

积分
7.00
发表于 2020-9-27 10:15:01 | 显示全部楼层
断言失败的原因为在调试模式会有你说的问题在
发布版本模式就没有mfc类库不推荐这么做,因为在cpu场景切换时可能丢失数据
如果你想做 把出现断言错误的地方不执行CFrameWnd::AssertValid()即可
回复

使用道具 举报

1

主题

9

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-9-27 10:30:01 | 显示全部楼层
怎么不执行CFrameWnd::AssertValid()呢?
这是mfc的类库函数里面的东东啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

快速回复 返回顶部 返回列表