CAD开发者社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

AutoCAD 2023 开发者帮助

自定义对象的长事务问题

2024-5-18 19:00| 发布者: admin| 查看: 123| 评论: 0|原作者: admin|来自: AutoCAD

自定义对象的长事务问题

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

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

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

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

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

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

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

以下是一些示例:

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

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

  • 如果上述映射已被覆盖,也可以从对象的方法中完成。wblockClone()
  • 如果引用是对象的数据成员,则使用 ,则可以避免长事务有效性测试。测试是通过使用一种类型的文件管理器归档 ID 来完成的。为避免测试,请勿在此类归档期间将不需要克隆的 ID 归档。但是,请勿在此文件之外保留任何所有权 ID,否则使用此文件管理器的其他功能(如部分保存和加载)可能无法正确处理您的对象。要从此文件管理器中保留的唯一安全 ID 是 和 对象。dwgOutFields()kIdFilerAcDbSoftPointerIdAcDbHardPointerId
  • 如果它确实在持久反应堆中,则可以使用反应堆迭代器找到它。下面是字典对象如何查找 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();
}

父主题:

  1. 派生自 AcDbObject

路过

雷人

握手

鲜花

鸡蛋

最新评论

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

GMT+8, 2025-3-5 17:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

返回顶部