Code Red > .NET

Autocad crashing due to unreferenced object

(1/3) > >>

Keith™:
This is another head scratcher.

I have a form class with some controls on it. It's irrelevant what controls at this point.
I invoke the form from an AutoCAD commandmethod, this is a static function so I either need to make the form static or have an explicit instance defined in the function.

Because I want to share data between drawings from within the form, I can't just create a new form in each drawing, so I have a private static instance defined.

In my commandmethod, I check null and disposed before operating on them, if either are true, I instantiate a new form, otherwise I just bring it to the front.

Herein lies the problem. If the form gets disposed somehow (it happens occasionally, still working on that) and I instantiate a new one, it will work fine in the current drawing, but if I open a new drawing or switch to a different drawing, the DocumentBecameCurrent event fires from the disposed form and crashes AutoCAD because everything has been disposed.

I've tried removing the event handler if the form is being disposed, but that doesn't seem to be working.

I am certain it has something to do with the static object getting disposed while an application level event is still active.

Thoughts?

MickD:
Here's what I have for a similar situation, it handles the form and changing doc events, hope it helps.


--- Code - C#: ---        private static My_MainFrm form;        private static bool docevent;         /// <summary>        /// Loads the MyApp Main Form        /// </summary>        [CommandMethod("MYAPP")]        public static void MyApp()        {            // set the doc event handler:            if (!docevent)            {                _AcAp.Application.DocumentManager.DocumentBecameCurrent +=                       docCollDocActivated;                docevent = true;            }             if (form == null || form.IsDisposed)            {                form = new My_MainFrm();            }            _AcAp.Application.ShowModelessDialog(null, form, false);        }                // the doc event handler:        public static void docCollDocActivated(object senderObj, DocumentCollectionEventArgs docColDocActEvtArgs)        {            if (form != null && form.Visible)            {                NativeMethods.SetFocusToEditor(_AcAp.Application.MainWindow.Handle);                form.UpdateDocument(); // form method to update dialog with current doc data            }        } 
And the native methods helper class (there may be better ways now, this code is getting on a bit now :) ). The one and only method didn't need to go into it's own class but I was preparing for further native methods if/when required.
it just sets the focus back to the drawing editor when changing drawings or showing the dialog and may not be needed (but is handy).


--- Code - C#: ---public class NativeMethods    {        [DllImport("user32.dll")]        private static extern IntPtr SetFocus(IntPtr hwnd);         public static void SetFocusToEditor(IntPtr hwnd){             SetFocus( hwnd );        }    } 

It's Alive!:
How are you creating the events? In the form? If you might be able to override Dispose in the form to unload your reactor

Keith™:

--- Quote from: It's Alive! on April 01, 2020, 10:41:25 PM ---How are you creating the events? In the form? If you might be able to override Dispose in the form to unload your reactor

--- End quote ---

In the form, but now that I've looked at the example MickD provided, I am thinking I should just move it to the commandmethod. This will ensure there is only ever one event handler and setting the bool prevents multiple handlers.

Thanks for the ideas...now to see if this resolves my problems.

gile:
Hi,

Maybe I misunderstand the issue but, according it seems to me it's safer to always dispose a modal dialog after used, you can get the data from properties of the instance of dialog and store them as static members in the class containing the CommandMethod so that they're accessible between drawings.

Here's a minimalist example with a sort of input box.

Dilaog class:

--- Code - C#: ---using System.Windows.Forms; namespace SeparationOfConcernSample{    public partial class DialogBox : Form    {        public string Data1 => textBox1.Text;         public DialogBox(string data1)        {            InitializeComponent();            textBox1.Text = data1;        }    }} 
Commands class:

--- Code - C#: ---using Autodesk.AutoCAD.Runtime; using System.Windows.Forms; using AcAp = Autodesk.AutoCAD.ApplicationServices.Application; namespace SeparationOfConcernSample{    public class Commands    {        static string data1 = "";         [CommandMethod("INPUT")]        public static void InputCmd()        {            using (var dialog = new DialogBox(data1))            {                if (AcAp.ShowModalDialog(dialog) == DialogResult.OK)                {                    data1 = dialog.Data1;                }            }        }         [CommandMethod("OUTPUT")]        public static void OutputCmd()        {            AcAp.ShowAlertDialog(data1);        }    }} 

Navigation

[0] Message Index

[#] Next page

Go to full version