找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 858|回复: 19

[求助] 块表记录问题【已解决】

[复制链接]

已领礼包: 4个

财富等级: 恭喜发财

发表于 2020-7-8 17:59:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 rwss009 于 2020-7-10 15:26 编辑

先说一下大致内容,我先用arx创建了一个自定义实体,由多段线绘制,然后每个点的坐标存在mysql数据库中,我使用mysql connector c++连接数据库,读取到这些点坐标后,就通过他们绘制多段线,然后将该自定义实体添加到cad的模型空间中,函数为PostToModelSpace( AcDbEntity *pEnt) ,其中这个参数就是要添加的自定义实体。

一直是可以正常绘制的,但由于需求,不能只绘制一次结束,所以我在cad加载arx文件时创建了一个线程,将之前的功能函数(读写数据库等操作)放入这个线程中,设置为死循环。查询一次数据库中有没有需要绘制的内容,有的话就通过构造自定义实体绘制,然后将实体加入cad块表中。如果没有则Sleep一段时间再查找。大致流程就是这样子。

但现在出现了问题,数据库中我先设置好,线程中的循环执行第一次时候,是可以成功绘制的。绘制完之后该线程Sleep等待。这时我修改数据库,再设置为需要绘制的状态。然后该线程Sleep之后发现需要绘制,就继续准备绘制该实体。

程序一直到读取数据库中坐标、构造自定义实体的步骤都没有问题。但在执行PostToModelSpace( AcDbEntity *pEnt)这个函数时,到了获得模型空间对应的块表记录这一步,出了问题,pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd,AcDb::kForWrite);这条语句执行后,pBlkTblRcd的值为空,而且getAt()返回的不是Acad::eOk。导致实体要添加到该块表记录时报异常。

所以求助一下,这里为什么pBlkTblRcd的值为空?调试时发现pBlkTbl的地址没有变过,即使是线程Sleep之后执行到这里地址也没有变化,但之前就可以成功运行,再运行时为什么就得不到pBlkTblRcd的值?

以下贴PostToModelSpace( AcDbEntity *pEnt)的代码:
  1. AcDbObjectId PostToModelSpace( AcDbEntity *pEnt)
  2. {
  3.         assert(pEnt);
  4.         // 获得当前图形数据库的块表
  5.         AcDbBlockTable *pBlkTbl = NULL;
  6.         acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl,AcDb::kForRead);

  7.         // 获得模型空间对应的块表记录
  8.         AcDbBlockTableRecord *pBlkTblRcd = NULL;
  9.         if(pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd,AcDb::kForWrite) != Acad::eOk)
  10.         {
  11.                 pBlkTbl->close();
  12.                 delete pEnt;
  13.                 pEnt = NULL;
  14.                 acutPrintf(_T("创建块表记录指针失败"));
  15.                 return AcDbObjectId::kNull;
  16.                
  17.         }
  18.         // 将实体添加到模型空间的块表记录
  19.         AcDbObjectId entId = NULL;
  20.         Acad::ErrorStatus es = pBlkTblRcd->appendAcDbEntity(entId, pEnt);
  21.         if (es != Acad::eOk)
  22.         {
  23.                 pBlkTblRcd->close();
  24.                 delete pEnt;        // 添加失败时,要delete
  25.                 pEnt = NULL;

  26.                 return AcDbObjectId::kNull;
  27.         }

  28.         // 关闭模型空间块表记录和实体
  29.         pBlkTbl->close();
  30.         pBlkTblRcd->close();
  31.         pEnt->close();

  32.         return entId;
  33. }
复制代码


如需其他内容,请告知,我继续解释

问题已解决,详情请参考12楼,多谢给我回复的人,尤其是 @edata 给了我极大帮助

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2020-7-10 11:24:20 | 显示全部楼层
eLockViolation 一般是没有锁定文档造成的。
你用的线程等于是非模态访问数据库,必须要先锁定文档再执行访问数据库。
  1. // 类似于非模态对话框,需要锁定和解锁文档
  2. acDocManager->lockDocument(acDocManager->curDocument());
  3. // 绘制一条直线
  4. AcGePoint3d startPt(4.0, 2.0, 0.0);
  5. AcGePoint3d endPt(10.0, 7.0, 0.0);
  6.     AcDbLine *pLine = new AcDbLine(startPt, endPt);
  7. AcDbBlockTable *pBlockTable;
  8. acdbHostApplicationServices()->workingDatabase()
  9. ->getSymbolTable(pBlockTable, AcDb::kForRead);
  10. AcDbBlockTableRecord *pBlockTableRecord;
  11. pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
  12. AcDb::kForWrite);
  13. pBlockTable->close();
  14. AcDbObjectId lineId;
  15. pBlockTableRecord->appendAcDbEntity(lineId, pLine);
  16. pBlockTableRecord->close();
  17. pLine->close();
  18. acDocManager->unlockDocument(acDocManager->curDocument());
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 1 反对 0

使用道具 举报

发表于 2020-7-8 21:50:39 | 显示全部楼层
AcDb::kForWrite 写模式只能有打开一次.如果对象已经打开了没关闭,再次打开就会失败.
其次是多线程操作有可能设置到是非模态操作数据库,考虑加一个文档锁定再操作,避免一些问题.
最主要的还是看你的返回值
acutPrintf(_T("\n打开对象失败!,错误码: %s"),acadErrorStatusText(es));
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 1 反对 0

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

发表于 2020-7-8 18:13:05 | 显示全部楼层
AUTOCAD不是一个对多线程支持很好的软件,
不返回EOK,那么返回的是什么?看给你的是什么提示
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 1 反对 0

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-9 17:00:17 | 显示全部楼层
newer 发表于 2020-7-8 18:13
AUTOCAD不是一个对多线程支持很好的软件,
不返回EOK,那么返回的是什么?看给你的是什么提示

额,我按照3楼的方法在打印“创建失败”那里修改了打印输出

[Actionscript3] 纯文本查看 复制代码
acutPrintf(_T("\n打开对象失败!,错误码: %s"),acadErrorStatusText(es));


但是在cad的命令那里并没有显示任何东西,您知道这是怎么回事吗?
(初学时通过输入命令执行acutPrintf(_T("hello")); 是会打印出来的。)
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-9 17:08:15 | 显示全部楼层
edata 发表于 2020-7-8 21:50
AcDb::kForWrite 写模式只能有打开一次.如果对象已经打开了没关闭,再次打开就会失败.
其次是多线程操作有 ...

其实那些打印输出现在都是虚设,cad中没有打印出任何东西,,您知道这是怎么回事吗?
(初学时通过输入命令执行acutPrintf(_T("hello")); 是会打印出来的。)

还有您说的AcDb::kForWrite写模式只能打开一次,我感觉可能会与这个问题有关,因为第一次打开就成功了。
但不知道的是您说的“如果对象已经打开了没关闭,再次打开就会失败.”,这里的关闭,是不是指我代码中的
pBlkTbl->close();
pBlkTblRcd->close();
pEnt->close();
这些关闭?还是说需要再写什么代码才可以关闭?
还有那俩个方面,我从网上继续参考参考,多谢高人指路!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 19个

财富等级: 恭喜发财

发表于 2020-7-9 18:19:15 | 显示全部楼层
rwss009 发表于 2020-7-9 17:00
额,我按照3楼的方法在打印“创建失败”那里修改了打印输出

[mw_shl_code=actionscript3,true]

应该是焦点的问题吧,你直接得到命令窗口句柄,直接往里面打印试试。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2020-7-9 21:30:00 | 显示全部楼层
个人建议还是先学一学vs断点调试,返回的es值是什么,一目了然.
es就会包含可能出错的原因.好对症下药.
关闭是指的close()这个,如 pBlkTblRcd->close();
比如你在前面的代码中打开了模型空间,而又在这个函数中再次写打开,就会出现打开失败...
至于具体是什么情况,得看到全部代码才好分析.
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-10 09:05:55 | 显示全部楼层
edata 发表于 2020-7-9 21:30
个人建议还是先学一学vs断点调试,返回的es值是什么,一目了然.
es就会包含可能出错的原因.好对症下药.
关 ...

C:\Users\ACER\Desktop\65iyth.png
不知道本地的图片能不能上传,我有点钻牛角尖了,差点忘了一直用的调试就想着在那打印输出。

es的返回的是 eLockViolation,多谢指点,我也从文档上查一查
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-10 09:07:59 | 显示全部楼层
Lisphk 发表于 2020-7-9 18:19
应该是焦点的问题吧,你直接得到命令窗口句柄,直接往里面打印试试。

是不是因为线程没结束所以打印不到命令那里呢?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-10 09:30:13 | 显示全部楼层
之前的图片

之前的图片

之前的图片
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-10 09:43:15 | 显示全部楼层
edata 发表于 2020-7-9 21:30
个人建议还是先学一学vs断点调试,返回的es值是什么,一目了然.
es就会包含可能出错的原因.好对症下药.
关 ...

这个是第一次的调试信息,可见到pBlkTblRcd是有值的,第一次的绘制成功了

第一次绘制时的调试信息

第一次绘制时的调试信息




然后线程进入sleep,修改数据库,线程sleep完准备再次绘制,然后pBlkTblRcd就没有值了。

再次绘制时的调试信息

再次绘制时的调试信息


es返回值为 eLockViolation ,pBlkTblRcd那里存在如图所示的错误。

多谢解惑!感激不尽!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-10 15:14:04 | 显示全部楼层
edata 发表于 2020-7-10 11:24
eLockViolation 一般是没有锁定文档造成的。
你用的线程等于是非模态访问数据库,必须要先锁定文档再执行 ...

多谢大哥,我从网上也是有说类似的解决方法,但还是你这个详细,感谢。

不过,我加上这两行代码后,却报了链接错误,我已经加了头文件#include <acdocman.h>,是不是还需要在附加依赖项里添加某些lib?

报链接错误

报链接错误


vs 2008 , objectarx 2010 ,都是x64。 版本较低但属实没办法。

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 4个

财富等级: 恭喜发财

 楼主| 发表于 2020-7-10 15:22:09 | 显示全部楼层
edata 发表于 2020-7-10 11:24
eLockViolation 一般是没有锁定文档造成的。
你用的线程等于是非模态访问数据库,必须要先锁定文档再执行 ...

哦哦不用管这个错了,我之前是在函数PostToModelSpace()的实现中添加,报了错。

现在我添加到了外部线程函数里就可以运行了,而且效果正确了。再添加一个刷新的功能应该就可以了。

太感谢您了,这个问题困扰我好几天了,网上搜索都是没有一点相关的,没有您的指点,我可能得磨一个星期!感谢感谢!如何给您加D豆?我要把我的全给你加了!

点评

你这个监视数据库,然后实时更新的,工程文件能否传上来和大家分享下,谢谢!  详情 回复 发表于 2020-7-11 02:17
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 145个

财富等级: 日进斗金

发表于 2020-7-11 02:17:30 | 显示全部楼层
rwss009 发表于 2020-7-10 15:22
哦哦不用管这个错了,我之前是在函数PostToModelSpace()的实现中添加,报了错。

现在我添加到了外部线 ...

你这个监视数据库,然后实时更新的,工程文件能否传上来和大家分享下,谢谢!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-4-20 04:04 , Processed in 0.279386 second(s), 63 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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