Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Object/Structure References [modified]

Object/Structure References [modified]

Scheduled Pinned Locked Moved Visual Basic
data-structureshelpc++
8 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    Ed Hill _5_
    wrote on last edited by
    #1

    I am working on quite a large form that has become very slow to load, so i'm looking to take off some of the controls and have them loading on a background worker. The most used controls will remain, and a stack will be set up of controls to load in the background, loading the most recently requested control next. As controls can only be added on the main thread there is also a queue of controls that have been loaded on the background worker and now need adding to the form. All of this works, the issue i have is it would be useful to keep a reference to each control, so you only load it once etc. To stop code replication it would be great if i can create an object by sending in the System.Type of the object i want to make, the controlCollection it should be added to, some data it can use and the class/form level referance you want set to the control when it has loaded. Most of this works, however, i cannot get the class level reference to point to object created on the background worker. I get the feeling it should be doable using byRef, but am not quite sure how. I'm thinking my C++ way of thinking is causing problems here, any advice would be appreciated. Sorry for the large amount of code being posted, think it is all needed to solve the problem.

    Public Class MyClass
    'class level declaration of control to load on the background worker
    Private _addresses As uscAddresses = Nothing

    Public Function Addresses() As uscAddresses
        If \_addresses Is Nothing Then 'if its not been loaded we should put it on the top of the stack
            'don't worry if it is already on the stack as it will not get loaded twice
            \_loadQueue.Push(New ComponentToLoad(GetType(uscAddresses), \_addresses, Nothing, tpAddresses))
            'if we are already running the background worker no need to start it a second time
            If Not bgwLoader.IsBusy Then bgwLoader.RunWorkerAsync()
            'ideally won't need this next bit in the final solution
            While \_addresses Is Nothing
                'Application.DoEvents()
                'Threading.Thread.Sleep(100)
            End While
        End If
        Return \_addresses
    End Function
    
    Structure ComponentToLoad
        Public Type As System.Type 'type of object that we want to load
        '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
        Public Target As UserControl 'the class level reference to use for the created object
        '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
    
    J D E 3 Replies Last reply
    0
    • E Ed Hill _5_

      I am working on quite a large form that has become very slow to load, so i'm looking to take off some of the controls and have them loading on a background worker. The most used controls will remain, and a stack will be set up of controls to load in the background, loading the most recently requested control next. As controls can only be added on the main thread there is also a queue of controls that have been loaded on the background worker and now need adding to the form. All of this works, the issue i have is it would be useful to keep a reference to each control, so you only load it once etc. To stop code replication it would be great if i can create an object by sending in the System.Type of the object i want to make, the controlCollection it should be added to, some data it can use and the class/form level referance you want set to the control when it has loaded. Most of this works, however, i cannot get the class level reference to point to object created on the background worker. I get the feeling it should be doable using byRef, but am not quite sure how. I'm thinking my C++ way of thinking is causing problems here, any advice would be appreciated. Sorry for the large amount of code being posted, think it is all needed to solve the problem.

      Public Class MyClass
      'class level declaration of control to load on the background worker
      Private _addresses As uscAddresses = Nothing

      Public Function Addresses() As uscAddresses
          If \_addresses Is Nothing Then 'if its not been loaded we should put it on the top of the stack
              'don't worry if it is already on the stack as it will not get loaded twice
              \_loadQueue.Push(New ComponentToLoad(GetType(uscAddresses), \_addresses, Nothing, tpAddresses))
              'if we are already running the background worker no need to start it a second time
              If Not bgwLoader.IsBusy Then bgwLoader.RunWorkerAsync()
              'ideally won't need this next bit in the final solution
              While \_addresses Is Nothing
                  'Application.DoEvents()
                  'Threading.Thread.Sleep(100)
              End While
          End If
          Return \_addresses
      End Function
      
      Structure ComponentToLoad
          Public Type As System.Type 'type of object that we want to load
          '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
          Public Target As UserControl 'the class level reference to use for the created object
          '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
      
      J Offline
      J Offline
      Johan Hakkesteegt
      wrote on last edited by
      #2

      This sounds a bit like you are trying to solve a basic simple problem with a really really really complicated solution. From the way you are trying to solve this problem now, I understand that even when the form is loaded completely, the user won't need all the controls all the time anyway. Wouldn't it be easier to just rethink your GUI design? No program should need so many buttons, text boxes, or whatever, that an average PC starts having trouble loading the interface. Even if you were to get your solution to work, your app would likely bring the PC to its knees anyway, by the time the background thread has finished loading all controls. Try to combine controls, and reuse them, or to move certain secondary functionality (and the accompanying controls) to its own form, which you then open with a single button or automatically, as a result of another action taken or choice made.

      My advice is free, and you may get what you paid for.

      E 1 Reply Last reply
      0
      • J Johan Hakkesteegt

        This sounds a bit like you are trying to solve a basic simple problem with a really really really complicated solution. From the way you are trying to solve this problem now, I understand that even when the form is loaded completely, the user won't need all the controls all the time anyway. Wouldn't it be easier to just rethink your GUI design? No program should need so many buttons, text boxes, or whatever, that an average PC starts having trouble loading the interface. Even if you were to get your solution to work, your app would likely bring the PC to its knees anyway, by the time the background thread has finished loading all controls. Try to combine controls, and reuse them, or to move certain secondary functionality (and the accompanying controls) to its own form, which you then open with a single button or automatically, as a result of another action taken or choice made.

        My advice is free, and you may get what you paid for.

        E Offline
        E Offline
        Ed Hill _5_
        wrote on last edited by
        #3

        While i understand your points, the application i am working on is a product that has been in development and use for many years, and i'm quite restricted in what i can do to change where information is displayed. I think the C++ example of what i want is something like this:

        //main.cpp
        #include <iostream>
        #include <stdlib.h>
        #include "objTest.h"

        void main()
        {
        int toSet = 0;
        objTest middleMan = objTest();
        middleMan.setRef(&toSet);
        middleMan.set(10);
        //pause the app before quiting
        std::cout<<toSet;
        char c;
        std::cin>>c;
        }
        // objTest.h
        #pragma once

        class objTest
        {
        public:
        objTest(void);
        ~objTest(void);
        void setRef(int* newRef)
        {
        myVal = newRef;
        }
        void set(int newVal)
        {
        *myVal = newVal;
        }
        private:
        int* myVal;
        };

        This is really quite simple and can be very powerful when used correctly, but i'm guessing not something that can be done in VB.

        J 1 Reply Last reply
        0
        • E Ed Hill _5_

          I am working on quite a large form that has become very slow to load, so i'm looking to take off some of the controls and have them loading on a background worker. The most used controls will remain, and a stack will be set up of controls to load in the background, loading the most recently requested control next. As controls can only be added on the main thread there is also a queue of controls that have been loaded on the background worker and now need adding to the form. All of this works, the issue i have is it would be useful to keep a reference to each control, so you only load it once etc. To stop code replication it would be great if i can create an object by sending in the System.Type of the object i want to make, the controlCollection it should be added to, some data it can use and the class/form level referance you want set to the control when it has loaded. Most of this works, however, i cannot get the class level reference to point to object created on the background worker. I get the feeling it should be doable using byRef, but am not quite sure how. I'm thinking my C++ way of thinking is causing problems here, any advice would be appreciated. Sorry for the large amount of code being posted, think it is all needed to solve the problem.

          Public Class MyClass
          'class level declaration of control to load on the background worker
          Private _addresses As uscAddresses = Nothing

          Public Function Addresses() As uscAddresses
              If \_addresses Is Nothing Then 'if its not been loaded we should put it on the top of the stack
                  'don't worry if it is already on the stack as it will not get loaded twice
                  \_loadQueue.Push(New ComponentToLoad(GetType(uscAddresses), \_addresses, Nothing, tpAddresses))
                  'if we are already running the background worker no need to start it a second time
                  If Not bgwLoader.IsBusy Then bgwLoader.RunWorkerAsync()
                  'ideally won't need this next bit in the final solution
                  While \_addresses Is Nothing
                      'Application.DoEvents()
                      'Threading.Thread.Sleep(100)
                  End While
              End If
              Return \_addresses
          End Function
          
          Structure ComponentToLoad
              Public Type As System.Type 'type of object that we want to load
              '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
              Public Target As UserControl 'the class level reference to use for the created object
              '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
          
          D Offline
          D Offline
          Dave Kreskowiak
          wrote on last edited by
          #4

          Well, the other problem you have, besides loading way too many controls on a form, is performance when the form has to redraw itself. A large number of controls simply takes longer and longer to render and gets worse as you add controls. You cannot move this to a background thread. Back to your original problem, I don't really see this as a viable solution considering all controls have to be created on the UI thread. Creating them on a seperate thread causes problems for messages crossing thread boundries when they a dispatched from the app's message pump. You can very easily run into issues with your GUI that are funky and hard to replicated and diagnose.

          A guide to posting questions on CodeProject[^]
          Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
               2006, 2007, 2008
          But no longer in 2009...

          1 Reply Last reply
          0
          • E Ed Hill _5_

            While i understand your points, the application i am working on is a product that has been in development and use for many years, and i'm quite restricted in what i can do to change where information is displayed. I think the C++ example of what i want is something like this:

            //main.cpp
            #include <iostream>
            #include <stdlib.h>
            #include "objTest.h"

            void main()
            {
            int toSet = 0;
            objTest middleMan = objTest();
            middleMan.setRef(&toSet);
            middleMan.set(10);
            //pause the app before quiting
            std::cout<<toSet;
            char c;
            std::cin>>c;
            }
            // objTest.h
            #pragma once

            class objTest
            {
            public:
            objTest(void);
            ~objTest(void);
            void setRef(int* newRef)
            {
            myVal = newRef;
            }
            void set(int newVal)
            {
            *myVal = newVal;
            }
            private:
            int* myVal;
            };

            This is really quite simple and can be very powerful when used correctly, but i'm guessing not something that can be done in VB.

            J Offline
            J Offline
            Johan Hakkesteegt
            wrote on last edited by
            #5

            I understand your problem. In this light, I think you are right, your C++ way of thinking is causing you problems. I honestly don't know whether this can be done in VB or not, but I am certain VB was never meant for application control on that level. Considering that the GUI must be created on the main thread, and that all interaction between user and app also happens on the main thread, what exactly are you trying to achieve by loading the controls in groups? If you consider that a PC with a multi core CPU (which will actually handle two threads at the same time), should be strong enough to load your form the old way, and a single core processor will handle each thread alternatingly, so it won't really load any faster anyway, and loading controls in groups will limit the use of the loaded controls until all controls have been loaded? How about creating and placing groups of controls at runtime, upon some mouse-over event or something? A bit like MS Office or the windows start menu.

            My advice is free, and you may get what you paid for.

            E 1 Reply Last reply
            0
            • J Johan Hakkesteegt

              I understand your problem. In this light, I think you are right, your C++ way of thinking is causing you problems. I honestly don't know whether this can be done in VB or not, but I am certain VB was never meant for application control on that level. Considering that the GUI must be created on the main thread, and that all interaction between user and app also happens on the main thread, what exactly are you trying to achieve by loading the controls in groups? If you consider that a PC with a multi core CPU (which will actually handle two threads at the same time), should be strong enough to load your form the old way, and a single core processor will handle each thread alternatingly, so it won't really load any faster anyway, and loading controls in groups will limit the use of the loaded controls until all controls have been loaded? How about creating and placing groups of controls at runtime, upon some mouse-over event or something? A bit like MS Office or the windows start menu.

              My advice is free, and you may get what you paid for.

              E Offline
              E Offline
              Ed Hill _5_
              wrote on last edited by
              #6

              the advantage i am looking to gain is that the main form would load up quicker, and allow interaction with the initially loaded controls, the ones that are used most. The less used but still required can be loaded say on the tab they are on being selected, however this means there will always be a wailt when the tab is clicked on, even if its a small wait. If the controls are loaded in the background then they will be available. I agree that loading them when they are needed is a good solution, but if i could get them loaded while the app idles, or the user is doing other tasks it would just be a nice bonus. GUI items don't need to be created on the main thread, the only action that must occur on the main thread is adding the created control to say a tab page's control collection. This may be because i am not declaring them as with events, but the way the form is used is 95% for displaying data, there is very little user interaction with the form which is why i can load them on the background worker. Maybe its just me getting a little frustrated that VB won't let me implement whats in my head. Thanks for the advice though.

              J 1 Reply Last reply
              0
              • E Ed Hill _5_

                the advantage i am looking to gain is that the main form would load up quicker, and allow interaction with the initially loaded controls, the ones that are used most. The less used but still required can be loaded say on the tab they are on being selected, however this means there will always be a wailt when the tab is clicked on, even if its a small wait. If the controls are loaded in the background then they will be available. I agree that loading them when they are needed is a good solution, but if i could get them loaded while the app idles, or the user is doing other tasks it would just be a nice bonus. GUI items don't need to be created on the main thread, the only action that must occur on the main thread is adding the created control to say a tab page's control collection. This may be because i am not declaring them as with events, but the way the form is used is 95% for displaying data, there is very little user interaction with the form which is why i can load them on the background worker. Maybe its just me getting a little frustrated that VB won't let me implement whats in my head. Thanks for the advice though.

                J Offline
                J Offline
                Johan Hakkesteegt
                wrote on last edited by
                #7

                Jep, like I said, VB just isn't meant for control on that level. And if you are used to C++, and the level of control it affords, you are bound to feel some frustration every once in a while.

                My advice is free, and you may get what you paid for.

                1 Reply Last reply
                0
                • E Ed Hill _5_

                  I am working on quite a large form that has become very slow to load, so i'm looking to take off some of the controls and have them loading on a background worker. The most used controls will remain, and a stack will be set up of controls to load in the background, loading the most recently requested control next. As controls can only be added on the main thread there is also a queue of controls that have been loaded on the background worker and now need adding to the form. All of this works, the issue i have is it would be useful to keep a reference to each control, so you only load it once etc. To stop code replication it would be great if i can create an object by sending in the System.Type of the object i want to make, the controlCollection it should be added to, some data it can use and the class/form level referance you want set to the control when it has loaded. Most of this works, however, i cannot get the class level reference to point to object created on the background worker. I get the feeling it should be doable using byRef, but am not quite sure how. I'm thinking my C++ way of thinking is causing problems here, any advice would be appreciated. Sorry for the large amount of code being posted, think it is all needed to solve the problem.

                  Public Class MyClass
                  'class level declaration of control to load on the background worker
                  Private _addresses As uscAddresses = Nothing

                  Public Function Addresses() As uscAddresses
                      If \_addresses Is Nothing Then 'if its not been loaded we should put it on the top of the stack
                          'don't worry if it is already on the stack as it will not get loaded twice
                          \_loadQueue.Push(New ComponentToLoad(GetType(uscAddresses), \_addresses, Nothing, tpAddresses))
                          'if we are already running the background worker no need to start it a second time
                          If Not bgwLoader.IsBusy Then bgwLoader.RunWorkerAsync()
                          'ideally won't need this next bit in the final solution
                          While \_addresses Is Nothing
                              'Application.DoEvents()
                              'Threading.Thread.Sleep(100)
                          End While
                      End If
                      Return \_addresses
                  End Function
                  
                  Structure ComponentToLoad
                      Public Type As System.Type 'type of object that we want to load
                      '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
                      Public Target As UserControl 'the class level reference to use for the created object
                      '\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
                  
                  E Offline
                  E Offline
                  Ed Hill _5_
                  wrote on last edited by
                  #8

                  ok, i've got this all working now, i had to do something that i'm not massivly proud of, and i know its not very VB in its workings but here goes, just incase any one is in a similar situation. The issue i was having was that the reference in the structure would change to point at the newly created control, insted of pointing the class level object to point to the new control. I'm aware this is how things are designed to work, just lacks the ability to tell it how i want it working. So i wrapped the control in a class, like so.

                  Class uscHolder
                  Public ctrl As UserControl
                  Public Sub New()
                  ctrl = Nothing
                  End Sub
                  End Class

                  That way the structure will not change its reference to the new object, that will always point at the class level object. That way setting the usercontrol in the wrapper class is applied every where. Thanks agian for all the pointers, once i have a problem in my mind though even if its not the solution i use in the long run it will bug me untill i can think up a solution. When coding nothing should ever be impossible is a mindset i'm stuck with.

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups