块插入循环错误!dbobji.cpp@8638:eNotOpenForWrite

时间:2014-10-15 07:30:19

标签: c# .net autocad

美好的一天,

我正在创建一个程序来进行一些计算并在用户点击的位置插入一个块,然后重复计算并插入用户点击的任何其他点,直到用户取消(参见下面的程序) )。

程序在用户点击的第一点正确完成所有操作。然而第二次通过while循环,在用户点击一个点之后,程序导致致命错误并在不插入块的情况下崩溃Autocad,崩溃错误消息:“内部错误:!dbobji.cpp @ 8638:eNotOpenForWrite”。 / p>

有人请详细说明并向我解释我的问题所在吗?

谢谢,

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using System.Collections.Generic;
using System.Linq;

[assembly: CommandClass(typeof(Level_Arrow.Program))]

namespace Level_Arrow
{
    public class Program
    {
        [CommandMethod("LevelCalc")]
        public static void InsertBLock(string[] args)
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = acDoc.Editor;
            Database db = acDoc.Database;
            Transaction tr = db.TransactionManager.StartTransaction();

            PromptStringOptions blkN1 = new PromptStringOptions("");
            blkN1.Message = "\nSpecify Block Name: ";
            blkN1.AllowSpaces = true;
            blkN1.DefaultValue = "Level Arrow";
            PromptResult BlkN2 = ed.GetString(blkN1);
            string blkName = BlkN2.StringResult.ToString();

            BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);

            if (!bt.Has(blkName))
            {
                ed.WriteMessage("\nBlock not found.");
            }
            else
            {
                BlockTableRecord OrgBtr = (BlockTableRecord)tr.GetObject(bt[blkName], OpenMode.ForRead);

                PromptStringOptions pOptsUnitScale = new PromptStringOptions("");
                pOptsUnitScale.Message = "\nEnter drawing unit scale (m or mm): ";
                pOptsUnitScale.AllowSpaces = false;
                pOptsUnitScale.DefaultValue = "mm";
                PromptResult drgUnitsRes = ed.GetString(pOptsUnitScale);
                string drgUnits = drgUnitsRes.StringResult.ToLower();

                PromptDoubleOptions pOptsDrgScale = new PromptDoubleOptions("");
                pOptsDrgScale.Message = "\nEnter detail scale(1:_): ";
                PromptDoubleResult drgScale = ed.GetDouble(pOptsDrgScale);
                double drgScalem = drgScale.Value / 1000;
                double drgScalemm = drgScale.Value;

                PromptPointOptions ptBL = new PromptPointOptions("");
                ptBL.Message = "\nIndicate baseline: ";
                PromptPointResult ptBaseline = ed.GetPoint(ptBL);
                if (ptBaseline.Status == PromptStatus.Cancel) return;
                double yBase = ptBaseline.Value.Y;

                PromptDoubleOptions levelBL = new PromptDoubleOptions("");
                levelBL.Message = "\nSpecify Baseline level: ";
                PromptDoubleResult blLevel = ed.GetDouble(levelBL);
                double blLevelmm = blLevel.Value * 1000;
                double blLevelm = blLevel.Value;

                BlockReference insblkref;
                PromptPointOptions ptIns;
                Scale3d blkScale;
                AttributeReference ar;

                int a = 1;
                while (a == 1)
                {
                    using (DocumentLock LckDoc = acDoc.LockDocument())
                    {
                        using (tr)
                        {
                            ptIns = new PromptPointOptions("");
                            ptIns.Message = "\nSpecify insertion point: ";
                            PromptPointResult ptInsert = ed.GetPoint(ptIns);
                            if (ptInsert.Status == PromptStatus.Cancel) return;
                            double yInsert = ptInsert.Value.Y;

                            double ptVar = yInsert - yBase;
                            double ptLevel = 0;

                            ObjectId bdId = bt[blkName];
                            Point3d pt = ptInsert.Value;

                            insblkref = new BlockReference(pt, bdId);
                            insblkref.Rotation = 0;

                            if (drgUnits == "mm")
                            {
                                ptLevel = (blLevelmm + ptVar) / 1000;
                                blkScale = new Scale3d(drgScalemm, drgScalemm, drgScalemm);
                                insblkref.ScaleFactors = blkScale;
                            }
                            else if (drgUnits == "m")
                            {
                                ptLevel = blLevelm + ptVar;
                                blkScale = new Scale3d(drgScalem, drgScalem, drgScalem);
                                insblkref.ScaleFactors = blkScale;
                            }
                            double ptDisp = Math.Round(ptLevel, 3);

                            btr.AppendEntity(insblkref);

                            tr.AddNewlyCreatedDBObject(insblkref, true);

                            if (OrgBtr.HasAttributeDefinitions)
                            {
                                foreach (ObjectId id in OrgBtr)
                                {
                                    DBObject obj = tr.GetObject(id, OpenMode.ForRead);
                                    AttributeDefinition ad = obj as AttributeDefinition;

                                    if (ad != null && !ad.Constant)
                                    {
                                        ar = new AttributeReference();
                                        ar.SetAttributeFromBlock(ad, insblkref.BlockTransform);
                                        ar.Position = ad.Position.TransformBy(insblkref.BlockTransform);
                                        if (ad.Justify != AttachmentPoint.BaseLeft)
                                        {
                                            ar.AlignmentPoint.TransformBy(insblkref.BlockTransform);
                                        }
                                        if (ar.IsMTextAttribute)
                                        {
                                            ar.UpdateMTextAttribute();
                                        }
                                        ar.TextString = ptDisp.ToString();

                                        ObjectId arId = insblkref.AttributeCollection.AppendAttribute(ar);
                                        tr.AddNewlyCreatedDBObject(ar, true);
                                        break;
                                    }
                                }
                            }

                            tr.Commit();

                        } //Transaction end
                    } //Lock end

                    insblkref = null; //tried "insblkref.Dispose();" didn't work.

                } //while loop end
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我认为问题是这一行:

using (tr)

您之前声明了tr,稍后再使用它(在第二个循环中)。通常,您会在声明周围添加一个使用声明(即将Transaction tr = db.TransactionManager.StartTransaction();替换为using (Transaction tr = db.TransactionManager.StartTransaction())

原因是,在使用块结束时,传入的变量是关闭的&布置;这意味着您在完成交易之前就已经关闭了交易。