CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

ObjectARX 开发指南

自定义对象的长事务问题

2022-12-31 21:57| 发布者: admin| 查看: 290| 评论: 0|来自: AutoCAD

长事务可以防御由不应克隆的对象或未处理的对象间引用导致的常见问题。如果 LongTransactionManager (LTM) 发现它必须克隆过滤的类对象才能完成长事务,它将中止整个操作。如果它发现克隆 IdMap 中没有,它也会中止。checkOut()checkIn()AcDbSoftPointerIdAcDbHardPointerId

需要防止其对象作为克隆包含在长事务中的应用程序需要使用 function.andt 注册这些对象,因此当应用程序不存在时,将自动过滤其所有对象。AcApLongTransactionManager::addClassFilter()AcDbProxyEntityAcDbProxyObjec

Wblock 克隆处理所有硬指针引用,但深度克隆不需要映射任一类型的引用。这两种克隆类型都用于长事务,具体取决于事务的类型。如果应用程序使用这些类型的引用或 xdata 句柄之一,则其对象将从长事务中被拒绝,除非应用程序采取额外的步骤来处理引用。这意味着,如果未加载应用程序,则将自动阻止其对象和引用参与长事务,并且应在没有它的情况下保留任何数据。

使用长事务和深度克隆通知拦截其对象和引用的克隆,并添加所需的任何对象克隆或映射。有关此内容的更多信息,请参阅深层克隆通知文档和示例。

如果克隆了具有软指针引用的对象(或深层克隆中的硬指针引用),则应用程序必须确保引用 ID 作为映射的 ID 对或克隆的 ID 对位于 IdMap 中。当对象引用应用程序在图形中维护的某些通用字典时,通常使用映射。在深度克隆中,映射可能包含一个 IdPair,其中键 == 值。在图形之间的 wblock 克隆中,IdPair 会将一个数据库的字典映射到另一个数据库的字典。引用由应用程序使用通知回调中的 bothor 克隆。deepClone()wblockClone()

采取这些步骤将保证“传递闭合”。为了确保可以签出一组相互引用的对象,然后再次检入,而不会破坏对象的关系,所有关联的对象将一起检出。例如,如果将任何边界或关联图案填充本身传递到,则填充代码会将所有边界对象添加到要检出的对象列表中。这就是它实现传递闭包的方式。如果没有发生这种情况,LTM 将找到图案填充的软指针 ID 到其边界。如果它发现克隆中缺少如此引用的边界对象,则长事务将中止。如果不这样做,即使未对检出的图案填充进行任何更改,原始图案填充也会在检入时失去其关联性。checkOut()

有时,存在不需要解析的已知引用。一种情况是跟踪使用它的所有实体的对象。例如,块表记录保留使用它们的所有块参照的列表。只签出其中一个引用是正确的,因此您必须让长事务机制知道其余引用不需要克隆。有几种方法可以做到这一点。

以下是一些示例:

  • 如果应用程序知道引用了哪些对象,但不会克隆(at,,或通知),则可以将引用对象的对象 ID 添加到克隆中。建议的方法是将值设置为 和 不克隆。例如beginWblockObjects()beginDeepClone()beginCheckOut()IdMapNULLidPair
idMap.assign(idPair(id, AcDbObjectId::kNull, kFalse);

如果以后需要克隆对象,则会相应地更改对象。idPair

  • 上面的映射也可以从对象的方法中完成,如果它已经被覆盖。wblockClone()
  • 如果引用是对象的数据成员,则使用,则可以避免长事务有效性测试。测试是通过使用文件类型对 ID 进行归档来完成的。为避免测试,请勿在此类归档期间归档不需要克隆的 ID。但是,请勿在此文件中保留任何所有权 ID,否则使用此文件管理器的其他功能(如部分保存和加载)可能无法正确处理您的对象。要从此文件管理器中保留的唯一安全 ID 是 andobjects。dwgOutFields()kIdFilerAcDbSoftPointerIdAcDbHardPointerId
  • 如果它们实际上在持久反应器中,则可以使用反应器迭代器找到它。下面是字典对象如何查找其 ID 并将其 ID 添加到期间通知的示例。IDIdMapbeginWblockClone()
beginWblockClone(..., AcDbIdMapping& idMap)
{
    ...
    AcDbDictionaryIterator* pIter = pDict->newIterator();
    AcDbObject* pObj;
    for ( ; !pIter->done(); pIter->next()) {
        acdbOpenObject(pObj, pIter->objectId(), kForRead);
        AcDbVoidPtrArray* pReactors = pObj->reactors();
        void* pReactor;
        AcDbObjectId rId;
        MyReactor* pMyReactor;
        if (pReactors) {
            for (int i = 0; i < pReactors->length(); i++) {
                pReactor = pReactors->at(i);
                if (acdbIsPersistentReactor(pReactor)) {
                    rId = acdbPersistentReactorObjectId(pReactor);
                    if (acdbOpenObject(pMyReactor, rId, kForRead)
                            == eOk) {
                        pMyReactor->close(); 
                        AcDbIdPair idPair(rId, 
                            AcDbObjectId::kNull, kFalse);
                        idMap.assign(idPair);
                    }
                }
            }
        }
        pObj->close();
    }
    delete pIter;
    pDict->close();
}

路过

雷人

握手

鲜花

鸡蛋

最新评论

QQ|Archiver|CAD开发者社区 ( 苏ICP备2022047690号-1 )

GMT+8, 2024-5-19 11:54

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部