none
Initial form loading time RRS feed

  • Question

  • Hi

    I know its probably a daft question but.... its something i do not know im afraid? some more complicated things i know, some more simple things i dont :)

    Anyway

    My class Project is an addin to Autodesk Inventor. ( i have asked there already but was referred out as its not an Inventor issue).

    OK. I am experiencing a long delay of about 10 seconds when i first initiate the New form instance. Once this has been done, the form will load a New instance in about a second. This behaviour also occurs when there isnt any code firing on the forms Load event which tells me that its the New instance causing my the problem. This is how i am currently set up with my code:

    Public Class AddinGlobal
        Public Shared InventorApp As Inventor.Application
    
        Public Shared RibbonPanelId As String
        Public Shared RibbonPanel As RibbonPanel
        Public Shared ButtonList As New List(Of InventorButton)()
        Public Shared fForm As frmMain
        Public Shared FormInUse As Boolean = False
        Public Shared ThumbView As New InventorThumbnailViewLib.ThumbnailProvider

    I am not creating the member as a New member yet because im not permitted to. It can only be loaded into memory IF the Class is to be used (as selected by the user in the application menu).

    When the application menu button is clicked to invoke the addin, this is the code behind the button:

    Public Class ButtonActions
        Public Shared Sub Button1_Execute()
            
            Select Case AddinGlobal.FormInUse
                Case False
                    AddinGlobal.fForm = New frmMain
                    AddinGlobal.fForm.StartPosition = FormStartPosition.CenterScreen
                    AddinGlobal.fForm.Show()
                    AddinGlobal.FormInUse = True
            End Select
        End Sub
    End Class

    Note that here i create a New instance of the form in AddinGlobal. If i change the code and create the New instance in the AddinGlobal class, my form does load immediately however when i close it, it gets disposed and i cannot open or create it again. Obviously option 1 creates a form and the button creates a new instance and option 2 creates a new instance but i lose it when i close the form...

    so the question is:

    what is the best way to load a form as a new instance and dispose of it afterwards but allowing the user to create a new instance again if required? 

    thanks

    Nacho




    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 7:18 AM

All replies

  • If i change the code and create the New instance in the AddinGlobal class, my form does load immediately however when i close it, it gets disposed and i cannot open or create it again.

    That would be because it is shared.  Do you have a reason for declaring these members as Shared?   Shared members are subject to different instantiation rules then nonshared members, and this may be affecting your instance creation time.

    • Proposed as answer by Cor Ligthert Wednesday, January 31, 2018 10:06 AM
    Wednesday, January 31, 2018 9:49 AM
  • Hi

    Yes. I have some basic modules and other functions that require access to the form. When the form is not shared, i cannot access (or seem to access) the form controls and they become available if the form is shared.

    This is the point where you say ive probably done my project wrong right?

    I moved functions to a module to lighten the coding in the form itself.....

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 5:35 PM
  • Nigel,

    I've looked at my calendar and it really says 2018, not 1985 from the time of MS-Basic. 

    A module, who gave you the idea it would lighten the coding of your program?


    Success Cor


    • Edited by Cor Ligthert Wednesday, January 31, 2018 6:19 PM
    Wednesday, January 31, 2018 6:18 PM
  • I can take the sarcasm, its ok. :) We are all not blessed with the infinite knowledge that allows us to sit above the rest and be judgemental..

    I am self taught and learn most of my coding as i go. Probably not the ethical way but we are allowed to be self taught. I never used MS-Basic so i cant relate to that. No one gave me the idea. I recall reading somewhere that a module a container and a class is a reusable method. Many youtube videos dated 2017 use modules & classes. It wasnt to lighten my project code, it was to lighten the code in the form to make code easier to find and organised.

    anyway

    i can convert my modules to classes and have a different approach which maybe just may remove the need for sharing. im guessing something like

    Dim s As New MyConvertedModuleToClass(f As Form)

    f.MyControl.Text = "Something"

    however, until i declare f as the form, it doesnt know the control exists thus back to my issue of sharing...

    i'll find a way


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 6:35 PM
  • Hi

    Yes. I have some basic modules and other functions that require access to the form. When the form is not shared, i cannot access (or seem to access) the form controls and they become available if the form is shared.

    This is the point where you say ive probably done my project wrong right?

    I moved functions to a module to lighten the coding in the form itself.....

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    How big is the module? Does the form use all the functions?

    Do an experiment. Put the module functions in your form and see what happens. If it goes faster then there is your problem?

    You should not try to control controls between forms. Just pass data to a self contained form. But it all depends how much we are talking about. Sometimes you have to try it to see.


    Wednesday, January 31, 2018 6:39 PM
  • Hi

    The modules and coding are not very big or resource heavy. In fact, i completely turned off all code and had ONLY the form loading with no function calling and i still get anything from 5 to 10 seconds

    thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 6:43 PM
  • Hi

    The modules and coding are not very big or resource heavy. In fact, i completely turned off all code and had ONLY the form loading with no function calling and i still get anything from 5 to 10 seconds

    thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Nacho,

    So if I understand, the first time you load the form it takes 5-10 secs and then next time 1 sec?

    How many lines of code is the form? How many controls?

    Did you say you can change the behavior by changing code?

    I would say this is almost normal behavior. First time long and next faster. It is like the form is cached?

    Do you have other forms in the app that do not behave this way?

    Make a test maybe, with an empty form.

    You could hide the form instead of dispose? What data is it you need from the main app that is used in the form?

    Wednesday, January 31, 2018 6:51 PM

  • So if I understand, the first time you load the form it takes 5-10 secs and then next time 1 sec?

    How many lines of code is the form? How many controls?

    Did you say you can change the behavior by changing code?

    I would say this is almost normal behavior. First time long and next faster. It is like the form is cached?

    Do you have other forms in the app that do not behave this way?

    Make a test maybe, with an empty form.

    You could hide the form instead of dispose? What data is it you need from the main app that is used in the form?

    Hi

    It behaves the same even if there is no code firing when its loaded. I commented out all of the code and it still had this delay.

    There are 16 controls on the form.

    if i change the code in the AddinGlobal class to fForm As New frmMain, it loads immediately

    It is the only form in the application however, i do have 4 UserControls that get loaded into a panel that have different controls based on the task. I commented these out too when checking the delay time.

    i will test with a completely empty form. i have tested with my form while all code has been commented out

    I have to dispose of the form. Inventor apps are not allowed to maintain active if they are not being used. This is because there are lots of other addins that can be added and eventually it will slow down. the rules are: Create a form instance only when required, dispose after.

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 7:58 PM
  • I have some basic modules and other functions that require access to the form. When the form is not shared, i cannot access (or seem to access) the form controls and they become available if the form is shared.

    This is the point where you say ive probably done my project wrong right?

    I moved functions to a module to lighten the coding in the form itself.....

    'Shared' does not affect acces to the form.  You should show what the problem is with access, because if you are having a problem accessing the form sharing it is probably the wrong way to solve it.  You probably need to provide the modules with a reference to your form instance. 

    But there is no advantage is using a module for functions - if you did that in order to make it easier to get to the functions then that is the same problem as accessing the form.  It is always preferable to keep the functions as part of the object to which they relate, not off in a separate piece of code.

    Explain what these other modules are, how they get created, and exactly what the 'access' problem was.

    Wednesday, January 31, 2018 8:24 PM
  • Note that here i create a New instance of the form in AddinGlobal. If i change the code and create the New instance in the AddinGlobal class, my form does load immediately however when i close it, it gets disposed and i cannot open or create it again. Obviously option 1 creates a form and the button creates a new instance and option 2 creates a new instance but i lose it when i close the form...



    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

     Yes,  if the new instance of the form is closed it will be disposed.  However,  as long as you are setting FormInUse back to False when the Form is Closing,  there is no reason you should not be able to create another new instance of it.  However,  we don't really have any idea what code is where,  or how it all works together from just looking at the small snippets of code you posted.


    If you say it can`t be done then i`ll try it

    Wednesday, January 31, 2018 8:25 PM
  • Nigel,

    What is very strange is that you create in your classes a new frmMain and then use a module. It is the windows forms OOP way turned around.

    What I write you can normally not see it because it is in VB hidden inside the application framework. A program starts with in the Main module (yes a module) and in that module is written

    Application.Start(new Form1) what then happens is that the constructor takes over the first start. 

    Therefore begin with going to Project -> Program Properties, it should show up like this. 

    In fact it generates as you can see that startup module for windows forms. 

    Maybe you find my messages sometimes sarcastic. But they are not sarcastic to show how clever I am and stupid you are. If that was the case I would do it 3 times and the fun was over. It is that I want to prickle you to overthink yourself if you are on the right way. 


    Success Cor


    • Edited by Cor Ligthert Wednesday, January 31, 2018 8:40 PM
    Wednesday, January 31, 2018 8:39 PM
  • It behaves the same even if there is no code firing when its loaded. I commented out all of the code and it still had this delay.

    There are 16 controls on the form.

    if i change the code in the AddinGlobal class to fForm As New frmMain, it loads immediately

    Nacho,

    If it is not difficult you may want to rearrange once you figure how. Is that what you want? Or do you want to get what you have going?

    Just a couple ideas you can try if the others don't see something.

    If you want to fix what you have you can try declaring the form public in the module it will load with your app when the module loads. Then just show and hide it. Acad can mind its business. It does not know the difference. See if it works.

    If you can take it out of Acad and do the same thing. Are there any Acad depending things being used/called as the form loads?

    Then the usercontrols you try it without those same thing?

    PS If your app is hogging resources or slowing Acad down then that will happen one way or the other. That is a problem either way. So minimize your resources by not using them is one thing... how to make your form/control is another. I would think all those user controls could be eliminated by just drawing your own on the form. If the user controls are a resource problem etc. In fact is the form the only thing showing in Acad? Or is there another main form showing on the screen and then a second form is shown as required?


    PS Wait a minute ?

     Public Shared fForm As frmMain

     AddinGlobal.fForm = New frmMain

    Is frmMain the application startup form? Or do you have a sub Main?

    Wednesday, January 31, 2018 8:47 PM
  • Yes,  if the new instance of the form is closed it will be disposed.  However,  as long as you are setting FormInUse back to False when the Form is Closing,  there is no reason you should not be able to create another new instance of it.

    The member is declared shared.  A new instance will never be created - the New is ignored for a shared member.

    Wednesday, January 31, 2018 8:51 PM
  • The member is declared shared.  A new instance will never be created - the New is ignored for a shared member.

     Oh...  I did not see that it was Shared.  Now that i look again,  i see everything is declared as Shared.

    If you say it can`t be done then i`ll try it

    Wednesday, January 31, 2018 8:56 PM


  •  Oh...  I did not see that it was Shared.  Now that i look again,  i see everything is declared as Shared.

    If you say it can`t be done then i`ll try it

    Did you not see that I proposed the answer from Acamar direct without any message?

    Not that I thought it was complete the problem but to warn others to look at it. 

    :-)


    Success Cor

    Wednesday, January 31, 2018 9:09 PM
  • Hi

    its cool. :)

    My project is not a windows forms application, its a class application so there isnt any form listed as a startup.

    I'll open the project later and get some code out to show more of whats going on in relation to why the form is Shared and the errors i get when the form is not shared.

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 9:14 PM
  • Hi

    I can rearrange my project quite easily. The reason i used modules was to categorise / organise my coding. for example, all of the coding directly related to the Inventor API are in a module mInventorCalls. There are a lot of Inventor functions so keeping them together seems the right thing to do.

    also

    When my form loads, i do a have a BackgroundWorker that gets data from a database and places the data into the relevant controls. I have currently commented this out. When i change a setting in the form, the data is written back to the database. This is all using a BLL DAL method and is very fast as there isnt much data to collect.

    my app isnt hogging resources, in fact its quite light but as there could potentially be lots of addins within Inventor, collectively if they were all left running but hidden it would create a lag. Usually Inventor will just crash.

    I'll do a small video to show whats going on.

    Cheers


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 9:21 PM
  • Yea I saw the message from Ray and thought, maybe can he simply recreate his startup module. 

    You know the code which is created is simply this and if you set off Application framework you can use it as a separate module. (Only windows forms uses that application framework to please old VB6 developers, but there is nothing to avoid it normally).

        static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }

    It can that there will be a complaint about that you have to create a sub new in the form. 

    However, keep in mind that Windows Forms is written into the framework and in my perception is that done with OOP in mind and not with shared (static in C type program languages) in mind. 


    Success Cor


    • Edited by Cor Ligthert Wednesday, January 31, 2018 9:25 PM
    Wednesday, January 31, 2018 9:23 PM
  • Hi

    Ok i now have pro project open. To answer your questions first Tommytwotrain:

    There is no startup form, it is a Class library. not sure what you mean by a Sub Main. Here is my application properties tab

    I think i see what i need to do now. I am trying to reference my form from a class and i am passing all of the collected data to the form. That class is being instantiated by the form.. Not right.

    I think instead, i need to create properties in the class and populate them with the data. Then, from the form i should retrieve the data from the properties of the class. I understand this.

    I am going to change this and convert the modules to classes. Anything directly related to the form will go back in the form. I will then post back with any differences. This i think will fix some coding errors but i cant quite see how this will remedy the forms delay.

    By changing the member in the AddinGlobal to New, it does load up instantly but when i close the form and dispose of it, i can no longer access it and this is what i need to resolve

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 10:30 PM
  • I am trying to reference my form from a class and i am passing all of the collected data to the form. That class is being instantiated by the form.. Not right.

    There's nothing wrong with doing it like that.  But you must be careful how you reference the instance of the form in order to pass the data to it.  You must reference it using a variable provided by the form that refers to itself.  There are many ways to do tyhat.  See, for instance:
    https://vbdotnetblog.wordpress.com/forms/where-did-i-come-from/
    https://vbdotnetblog.wordpress.com/forms/pushing-results-back-to-the-main-form/

    Those examples refer to forms specifically, but apply to any class.

    By changing the member in the AddinGlobal to New, it does load up instantly but when i close the form and dispose of it, i can no longer access it and this is what i need to resolve

    You can't dispose of something declared with Shared - it will always have a non-zero reference count.  If you need a shared member (I don't think you do) then do not contemplate disposing and re-creating - it can't happen.   If you don't need the instance to  be shared, don't share it.

    Wednesday, January 31, 2018 10:40 PM
  • Hi

    I will look at the links now. If i change fForm to non shared, i get a bunch of errors "Reference to a non-shared member requires an object reference".

    How i am referencing the form in the methods is like this:

    AddinGlobal.fForm.SomeControl

    When the form shared, i dont get the errors. When it is not shared, i do get the errors


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 10:44 PM
  • Nacho,

    Yes what you say sounds right.

    "but when i close the form and dispose of it, i can no longer access it and this is what i need to resolve"

     " i can no longer access it" What doe3s that mean? You cant make a new instance a second time?

    Are you using the same name? When you dispose the first time does that dispose the original shared form as declared in the module? I am not sure. How do you "dispose" now?

    Also, I would try to find the problem before I rewrite, if easier.

    Oh finally I would love to see how you interact with AutoCAD, the basics, I would like to try? Do you have a good link that shows how in vb? A simple something to run in Acad? Does it still use autolisp for that or is it new now? Just if you have time sometime show me.

    PS Sub Main: Where you set the startup form on the project properties page you show you can select sub main. Then it calls that sub first when startup. You can launch your form from there. This is the old way from the olden days I guess. I am not sure the "proper way" to do what you do now.

    Wednesday, January 31, 2018 10:48 PM
  • Quote

     " i can no longer access it" What doe3s that mean? You cant make a new instance a second time?

    Public Class AddinGlobal
        Public Shared InventorApp As Inventor.Application
    
        Public Shared RibbonPanelId As String
        Public Shared RibbonPanel As RibbonPanel
        Public Shared ButtonList As New List(Of InventorButton)()
        Public fForm As frmMain
        Public Shared FormInUse As Boolean = False
        Public Shared ThumbView As New InventorThumbnailViewLib.ThumbnailProvider
    
        Private Shared mClassId As String
        Public Shared Property ClassId() As String
            Get
                If Not String.IsNullOrEmpty(mClassId) Then
                    Return AddinGlobal.mClassId
                Else
                    Throw New System.Exception("Error")
                End If
            End Get
            Set
                AddinGlobal.mClassId = Value
            End Set
        End Property
    End Class
    Public Class ButtonActions
        Public Shared Sub Button1_Execute()
    
            Select Case AddinGlobal.FormInUse
                Case False
                    AddinGlobal.fForm = New frmMain
                    AddinGlobal.fForm.StartPosition = FormStartPosition.CenterScreen
                    AddinGlobal.fForm.Show()
                    AddinGlobal.FormInUse = True
            End Select
        End Sub
    End Class

    In the button click event, i create a new instance of the fForm in AddinGlobal. After i have created the first instance with the delay, all future instances are instant. if i change the addinGlobal to this:

    Public fForm As frmMain

    and the button code to this (omitting the New):

    Select Case AddinGlobal.FormInUse
                Case False
                    AddinGlobal.fForm.StartPosition = FormStartPosition.CenterScreen
                    AddinGlobal.fForm.Show()
                    AddinGlobal.FormInUse = True
            End Select
    then i can only call the form once because i am disposing it and only 1 instance is being created when it loads


    In the FormClosed event, i simply have me.Dispose

    I am interacting with Inventor not Acad although, im sure they work in a similar way. In the past, i have interacted using DIESEL & Lisp but you can also interact with vba & vb.net. I'll see what links i can get, im very familiar with Acad and drawing packages in general and the process of creating objects in the design window should be relatively straight forward especially for you seeing as you have great knowledge of points and drawing lines, rectangles etc.



    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!


    • Edited by NachoShaw Wednesday, January 31, 2018 11:05 PM
    Wednesday, January 31, 2018 10:57 PM


  • In the FormClosed event, i simply have me.Dispose

    I am not sure that is right? Or it may not do what you think.

    I will defer to the others now.

    :)

    Wednesday, January 31, 2018 11:17 PM
  • ok thanks. Before this, i had

    AddinGlobal.fForm.dispose

    which was disposing the instance (or at least thats what i thought)

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 11:19 PM
  • In the button click event, i create a new instance of the fForm in AddinGlobal. After i have created the first instance with the delay, all future instances are instant.

    1 shared down, only 9 to go.

    Wednesday, January 31, 2018 11:25 PM
  • lol

    actually, some of the shared members (in bold) are set as default by Autodesk and are set like this in the addin template

    Public Shared RibbonPanelId As String
        Public Shared RibbonPanel As RibbonPanel
        Public Shared ButtonList As New List(Of InventorButton)()
        Public fForm As frmMain
        Public Shared FormInUse As Boolean = False
        Public Shared ThumbView As New InventorThumbnailViewLib.ThumbnailProvider
    
        Private Shared mClassId As String
        Public Shared Property ClassId() As String
            Get
                If Not String.IsNullOrEmpty(mClassId) Then
                    Return AddinGlobal.mClassId
                Else
                    Throw New System.Exception("Error")
                End If
            End Get
            Set
                AddinGlobal.mClassId = Value
            End Set
        End Property
    End Class


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, January 31, 2018 11:30 PM
  • actually, some of the shared members (in bold) are set as default by Autodesk and are set like this in the addin template

    If they require that code to be shared then there is likely nothing you can do about the initial delay.  The code is going to instantiate the class on first access, and since it is accessing its own instance to set the value, it can't be avoided.  Perhaps it works slightly differently in C#, or perhaps it just takes time to create the object.

    Thursday, February 1, 2018 2:06 AM
  • lol

    actually, some of the shared members (in bold) are set as default by Autodesk and are set like this in the addin template

    Public Shared RibbonPanelId As String
        Public Shared RibbonPanel As RibbonPanel
        Public Shared ButtonList As New List(Of InventorButton)()
        Public fForm As frmMain
        Public Shared FormInUse As Boolean = False
        Public Shared ThumbView As New InventorThumbnailViewLib.ThumbnailProvider
    
        Private Shared mClassId As String
        Public Shared Property ClassId() As String
            Get
                If Not String.IsNullOrEmpty(mClassId) Then
                    Return AddinGlobal.mClassId
                Else
                    Throw New System.Exception("Error")
                End If
            End Get
            Set
                AddinGlobal.mClassId = Value
            End Set
        End Property
    End Class


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Nacho,

    Sorry, cant keep quiet. So the user clicks a menu in Inventor and that calls ButtonActions?

    So each menu click you get another form?

    I still dont see where the form needs to be Public at all?. I guess that is what Acamar and everyone means?

    I made this example and it creates forms and disposes (as you are now btw) but it is not a shared public form it is.... well I guess I am not sure what it is? But the example works.

    Click the button on form1 and a new form2 is made. How is your app different? Or where am I getting confused?

    PS There is no difference in load times from first to second in this simple example.

    Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Static formNumber As Integer formNumber += 1 Dim Toolbar1 As New Form2(formNumber) Toolbar1.Show() End Sub End Class

    Second form:

    Public Class Form2
        Public Sub New(formNumber As Integer)
    
            ' This call is required by the designer.
            InitializeComponent()
    
            ' Add any initialization after the InitializeComponent() call.
            Label1.Text = "Toolbar " & formNumber.ToString
        End Sub
    
        Private Sub Form2_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
            Me.Dispose()
        End Sub
    End Class



    Thursday, February 1, 2018 3:01 AM
  • Hi

    Thanks to everyone for the help so far. You are correct in the fact that a button is create inside Inventor by the addin and is placed on the application ribbon menu. Whe nthe button is clicked, my addin form will appear. I only need 1 instance of the form. In my code examples, you cansee that i check to see if it already in use and if it is, do nothing ( i did this with a boolean member)

    I dont really mind where or how the form is created, it doesnt necessarily need to be in the AddinGlobal, i put it in there as this is called by inventor when the addin is loaded. The code itself could be behind the ButtonExecute and literally be created there. I think that by the time i have converted the modules and removed any class references back to the fForm, it may rectify itself.

    i'll know tomorrow :)

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Thursday, February 1, 2018 6:06 AM