Crash during interaction with Pallet and Doument

Crash during interaction with Pallet and Doument

Anonymous
Not applicable
607 Views
2 Replies
Message 1 of 3

Crash during interaction with Pallet and Doument

Anonymous
Not applicable

I'm having an issue where I receive an AccessViolationException was unhandled error debugging in AutoCAD 2017 using VS 2015 Community Update 3.

The crash occurs when I have my pallet docked with multiple drawing tabs open and I click on the x (to close) a non active drawing.

 

The crash doesn't identify a specific location in the code but it seems to be after my DocumentActivated event handler here:

 

Private Sub callback_documentActivated(ByVal sender As Object, ByVal e As DocumentCollectionEventArgs)

        If Not Application.DocumentManager.MdiActiveDocument Is Nothing Then
            ResetTree()
        Else
            'now update the tree view
            If Not BW_Palette Is Nothing Then
                BW_Palette.tvBom.Nodes.Clear()
            End If
        End If

        'MsgBox("Reset Tree")

    End Sub

 

 

reset tree eventually calls this function in the pallet code:

 

Private Sub CreateNewTree()

        Using locDoc As DocumentLock = Application.DocumentManager.MdiActiveDocument.LockDocument

            Dim currdb As Database = Application.DocumentManager.MdiActiveDocument.Database


            Dim AppdictId As ObjectId
            Dim DivDictId As ObjectId
            'Dim rb As ResultBuffer


            Dim Stool As cSerializationTool = New cSerializationTool()

            Try

                'set the object id for the application dictionary member variable
                AppdictId = Stool.GetApplicationDictionaryId("BellwetherDesignTech")

                'set the object id for the bom dictionary member variable
                DivDictId = Stool.GetObjectDictionaryId("BillOfMaterials", AppdictId)

                Using trans As Transaction = currdb.TransactionManager.StartTransaction()
                    Dim DivDict As DBDictionary
                    DivDict = trans.GetObject(DivDictId, OpenMode.ForRead, False)
                    Dim DivDictenum As DbDictionaryEnumerator = DivDict.GetEnumerator()

                    'get each plane xrecord from the structure dictionary
                    Do While DivDictenum.MoveNext
                        Dim CatDict As DBDictionary
                        CatDict = trans.GetObject(DivDictenum.Current.Value, OpenMode.ForRead, False)

                        Dim nod As Forms.TreeNode = tvBom.Nodes.Add(DivDictenum.Current.Key, DivDictenum.Current.Key)
                        nod.Tag = "BomCategory"

                        Dim de As New DictionaryEntry

                        For Each de In CatDict
                            Dim pmXrec As Xrecord = trans.GetObject(de.Value, OpenMode.ForRead, False)
                            Dim childNode As Forms.TreeNode = nod.Nodes.Add(de.Key.ToString, de.Key.ToString)
                            childNode.Tag = "PieceMark"

                            Dim BomData As ResultBuffer = pmXrec.Data

                            Dim TipTxt As String = "Description = " + BomData.AsArray(1).Value.ToString + ControlChars.Lf +
                                                   "Material = " + BomData.AsArray(2).Value.ToString + ControlChars.Lf +
                                                   "Quantity = " + CStr(BomData.AsArray.Count - 3)

                            childNode.ToolTipText = TipTxt

                            Dim reccnt As Integer = 1

                            For Each tval As TypedValue In BomData

                                If reccnt > 3 Then

                                    Dim hand As String = tval.Value.ToString
                                    Dim handlenode As Forms.TreeNode = childNode.Nodes.Add(hand, hand)
                                    handlenode.Tag = "PartHandle"

                                End If

                                reccnt += 1

                            Next

                        Next

                    Loop

                    trans.Commit()

                End Using

            Catch ex As Exception
                MsgBox("Problem with Dictionary...(CreateNewTree)")
            End Try

        End Using

    End Sub

 

It seems that the drawing is trying to close while the CreateNewTree Function still has access to the database. I have tried adding a BeginDocumentClose event handler and find that this is called after the DocumentActivated and by having a message box in here delays the close long enough to stop the program from crashing.

 

Any direction or help would be greatly appreciated.

0 Likes
Accepted solutions (1)
608 Views
2 Replies
Replies (2)
Message 2 of 3

ActivistInvestor
Mentor
Mentor
Accepted solution

The DocumentActivated event can occur at any time, including while a command is in-progress in the document that's being activated.

 

Because of that, you can't use the type of Transaction returned by StartTransaction(). You need to use an OpenCloseTransaction which you get by calling the TransactionManager's StartOpenCloseTransaction() method, or by just calling the OpenCloseTransaction's constructor.

 

Insofar as the document being activated when you close it, yes that's going to happen. If the document has unsaved changes, you will also be prompted to save or discard them (or cancel). So, You would have to determine if that's why the document is being activated. Looking at the Document's CommandInProgress property might tell you something. Although I think it might be better to not act directly in the DocumentActivated event, and instead defer your processing until the next idle event. In the DocumentActivated event, you would set a flag telling your Idle event handler that your UI needs to be updated. In the idle event handler, check (and clear) the flag, and if it was set, then try checking to see if the document is being closed. At the point when the Idle event is raised, the BeginDocumentClose event may have already been raised, which would tell you what's going on. And if you do have unsaved changes in the non-active document that you're trying to close, and the dialog appears asking if you want to save, discard, or cancel, and you choose cancel, then the document doesn't close, and you have to contend with that situation as well, which makes things even more complicated.

 

What I don't like about your code is that you are doing a complete refresh of your UI every time a different document is activated, and that's going to be problematic, in more ways than just the one issue you're having now (to wit, the situation I just cited).

 

I think the better way to solve your problem is to maintain a non-UI class that stores the data needed to update/refresh your UI, and have one instance of that class for each open document. When a document is activated, nothing in it has changed since the last time it was active, so it should be safe to cache the data needed to refresh your UI in an instance of a non-UI class, and use that rather than accessing the database directly when its associated document becomes active.

 

 

Message 3 of 3

Anonymous
Not applicable

Thanks Activist_Investor. This is all great information...exactly what I needed.

 

>>>> I agree with you here but I may need additional help understanding and implementing this.

>>>> I think the better way to solve your problem is to maintain a non-UI class that stores the data needed to update/refresh your UI, and have one instance of that class for each open document. When a document is activated, nothing in it has changed since the last time it was active, so it should be safe to cache the data needed to refresh your UI in an instance of a non-UI class, and use that rather than accessing the database directly when its associated document becomes active.

 

 

0 Likes