12 Replies - 5691 Views - Last Post: 23 April 2012 - 10:37 AM Rate Topic: -----

#1 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 05:55 AM

Hello,

In my main program I have a List of objects which is filled with new objects by a timer every 2 seconds. And those objects need to move across the main Form of my application.

The application runs smoothly for about 10 seconds and then it starts to slow down. (Because of too many objects in the list i think)
I use another timer to make every object of that list move. And on every 10ms it iterates the whole list.

So my question is:

Is there a way to avoid scrolling through the list and make my objects move or removing some obsolete objects that dont need to be in the list anymore without breaking the for each cycle?

Thank you

Is This A Good Question/Topic? 0
  • +

Replies To: How to avoid creating too many Objects in C#?

#2 Ryano121   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1461
  • View blog
  • Posts: 3,289
  • Joined: 30-January 11

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 06:25 AM

So basically the List is being populated with new objects after each tick without the previous set being deleted?

So surely before you populate the list with new objects you want to .Clear() the list of the unwanted objects?

If you go down this route however you need work through the case of the timer ticks clashing as this could cause some funky behaviour.
Was This Post Helpful? 1
  • +
  • -

#3 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 07:42 AM

View PostRyano121, on 23 April 2012 - 06:25 AM, said:

So basically the List is being populated with new objects after each tick without the previous set being deleted?

So surely before you populate the list with new objects you want to .Clear() the list of the unwanted objects?

If you go down this route however you need work through the case of the timer ticks clashing as this could cause some funky behaviour.


Yes, but if I clear the list i will lose all objects in it. I want to make the objects disappear one by one.

This is the code where I create the objects:

private void tm_CreateBombs_Tick(object sender, EventArgs e)
        {
            Bomba bran =new Bomba(rnd.Next(1, this.Width));
            Bombi.Add(bran);
            this.Controls.Add(bran.Nova);
            this.Refresh();
          
        }


And all of the objects have a Label with an Image in them, this is the Constructor:
 public Bomba(int pozicija)
        {
            Nova = new Label();
            Nova.BackColor = Color.Transparent;
            Nova.Size = new Size(slika.Width, slika.Height);
           
            Nova.Image = (Image) slika;
            X = rnd.Next(1, pozicija);
            Nova.Show();
        }



Do you have any Idea how to do this?
Was This Post Helpful? 0
  • +
  • -

#4 Ryano121   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1461
  • View blog
  • Posts: 3,289
  • Joined: 30-January 11

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 07:49 AM

So if you want the objects to be removed one by one, then each time you add one to the list, you get rid of the first one -

Bombi.Remove(0); // remove the first one added

Bombi.Add(Bran); // add the new one to the end

Was This Post Helpful? 0
  • +
  • -

#5 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 08:19 AM

I'm sorry, I probably didn't ask the question right.

Ill just describe the application so you can see what I need to do.

The "Bomba" objects are falling from the sky and the are going to hit a building or fall on the ground.
And every time a "Bomba" hits the ground, it should disappear. I know how to do that.

But what bothers me is that when I have one "Bomba" on the screen its all good, with two bombs it's good too. But after the third bomb the application starts to slow down and eventually it starts lagging very very much.

And I want to stop the lagging but I don't know how. I read that I can help the rendering process with DirectX somehow but it seems to complicated.

Thanks for the patience! :)
Was This Post Helpful? 0
  • +
  • -

#6 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6537
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 08:43 AM

First, stop trying to have the program micro-manage all the objects. Looping through the list takes time and is a sequencial process.

If you place the movement code in the bomba class then it can move itself. It won't matter if you have 1 or 50 because you won't be working through the list from front to back every 10ms.

This has the added benefit of allowing each bomba to have a different timing parameter. So one bomba can move at 10ms, while another at 15ms... giving a more dynamic action to the game.

This is a good example of shifting from procedural coding (where you application is following a procedure to get the job done) to Object Oriented where your code is Oriented toward putting as much power in the Object as possible: Reducing the load the program has to bear.
Was This Post Helpful? 2
  • +
  • -

#7 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 08:55 AM

View PosttlhIn`toq, on 23 April 2012 - 08:43 AM, said:

First, stop trying to have the program micro-manage all the objects. Looping through the list takes time and is a sequencial process.

If you place the movement code in the bomba class then it can move itself. It won't matter if you have 1 or 50 because you won't be working through the list from front to back every 10ms.

This has the added benefit of allowing each bomba to have a different timing parameter. So one bomba can move at 10ms, while another at 15ms... giving a more dynamic action to the game.

This is a good example of shifting from procedural coding (where you application is following a procedure to get the job done) to Object Oriented where your code is Oriented toward putting as much power in the Object as possible: Reducing the load the program has to bear.


The code for movement of the bombs is in the bombs class and it's a method named Move(), i'm looping the list to call the method for each object I create. Because otherwise it just appears on its end location and doesn't move.

Here is the code for the class :

public class Bomba
    {
        int X { get; set; }
        int Y { get; set; }
        int sirina { get; set; }
        int visina { get; set; }

        public Bitmap slika = new Bitmap(Resursi.MissleImage);
        Random rnd = new Random();

        public Label Nova { get; set; }
        int velocityY { get; set; }


        public Bomba(int pozicija)
        {
            velocityY = rnd.Next(1, 10);
            Nova = new Label();
            Nova.BackColor = Color.Transparent;
            Nova.Size = new Size(slika.Width, slika.Height);
           
            Nova.Image = (Image) slika;
            X = rnd.Next(1, pozicija);
            Nova.Show();
        }

        public void Move()
        {
            
                float nextY = Y + velocityY;

                Y += velocityY;

                Nova.Location = new Point(X, Y);
          
            
        }

Was This Post Helpful? 0
  • +
  • -

#8 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6537
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 09:08 AM

That's a great start! Really. But why is the control of the movement still in the main part of the application then?

Here's a thought. Create a timer in the main part of the application. A 'heartbeat' event gets raised each time the timer goes .Tick.

All your classes subscribe to the heartbeat. This way you have a single timer for the entire program and it helps keep everything synchronized.

Now instead of looping through a long list, each bomba will hear the main class's heartbeat. Every x heartbeats they tell themselves to move(). They all hear the event at the same time, instead of sequentially. You stop having a loop that does nothing by troll through the list.

This what we call breaking of a tightly bound relationship. Right now your main class is tightly bound to all the child classes (the bombas) and controls their every move. By taking all that away the main class is just responsible for itself, and the bombas are responsible only for themselves. And the only interaction between them is an event subscription.
Was This Post Helpful? 2
  • +
  • -

#9 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 09:15 AM

View PosttlhIn`toq, on 23 April 2012 - 09:08 AM, said:

That's a great start! Really. But why is the control of the movement still in the main part of the application then?

Here's a thought. Create a timer in the main part of the application. A 'heartbeat' event gets raised each time the timer goes .Tick.

All your classes subscribe to the heartbeat. This way you have a single timer for the entire program and it helps keep everything synchronized.

Now instead of looping through a long list, each bomba will hear the main class's heartbeat. Every x heartbeats they tell themselves to move(). They all hear the event at the same time, instead of sequentially. You stop having a loop that does nothing by troll through the list.

This what we call breaking of a tightly bound relationship. Right now your main class is tightly bound to all the child classes (the bombas) and controls their every move. By taking all that away the main class is just responsible for itself, and the bombas are responsible only for themselves. And the only interaction between them is an event subscription.


Thanks I think I got it. :) That should solve it!

But how do i generate the
heartbeat
event and how do I make a class subscribe to this event?
Was This Post Helpful? 0
  • +
  • -

#10 Ryano121   User is offline

  • D.I.C Lover
  • member icon

Reputation: 1461
  • View blog
  • Posts: 3,289
  • Joined: 30-January 11

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 09:23 AM

The heartbeat will be the Timer Tick. No need to recreate it.

When you create a new Bomba, you add the event handler reference -

Bomba b = new Bomba();
heartbeat.Tick += b.HandleHeartBeat;


Providing that you implement the Handle method with the required signature, all should be well.

Alternatively (and as a better solution), you can create a custom even that is raised when the Timer ticks.

Check out these for custom events.

http://www.dreaminco...das-and-events/

http://www.dreaminco...ny-other-forms/

This post has been edited by Ryano121: 23 April 2012 - 09:26 AM

Was This Post Helpful? 1
  • +
  • -

#11 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 09:32 AM

Thanks!!! :)
Was This Post Helpful? 0
  • +
  • -

#12 lordofduct   User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2668
  • View blog
  • Posts: 4,786
  • Joined: 24-September 10

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 10:28 AM

All the information given so far will be useful to some degree as it comes to design.

But what I have concern with is that you say you're seeing noticeable lag with only 3 Bombas on screen. A loop for 3 objects, and a call of a function, shouldn't be all that intense. And I have a feeling there is going to still be lag because of it.

A "heartbeat" event will still be just calling the function for you on all the objects... just a tiny bit more efficiently. But the difference between it and doing the loop yourself on only THREE objects is going to be so minor you will barely notice it.

See an event is just a delegate. And a delegate just contains a collection of references to functions. So when the delegate/event gets called it just loops over all the function references and calls them for you. It's a loop... just a more efficient loop, but a loop none the less.




Now I notice everything is Bitmaps, and it sounds to me like your using WinForms to display your graphics.

So let me guess, the "LAG" you see is actually a flickering of the graphical region like it's having a hard time drawing the screen.

WinForms uses DirectDraw, and this rendering pipe is kinda slow. What happens is the program will cycle through all onscreen controls from bottom to top (behind to infront) and redraws the controls to the Display buffer in DirectDraw. This buffer is what DirectDraw will use to draw the entire screen on the display refresh cycle, which is usually 50 or 60 times a second (50hz and 60hz modes).

Thing is there's no reason to redraw something that hasn't changed graphically, so instead only those controls that have changed (moved, changed state like a mouse over, or other deals) will be redrawn. Usually only 1 or 2 controls will ever change state at a time in a WinForm as such programs aren't usually that visually rich. This reduces the time it takes for the draw cycle.

If a lot of controls change though, the time it takes may take a few milliseconds longer. And because the display refreshes itself usually at about 60hz (60 times per second), this means if the draw pass takes longer than 16.666 milliseconds, the DirectDraw buffer will have invalid regions (white regions) when DirectDraw goes to draw the screen.

So in steps a mode called 'DoubleBuffer'. In this mode we create yet another buffer. We do all our draw cycles to this dummy buffer, and while it is considered invalid it locks itself. DirectDraw's buffer doesn't get updated, so as long as its invalid. DirectDraw just draws the "old" state of the screen. Once your draw pass completes, it gets placed into the DirectDraw buffer, and it then draws the screen. NO invalid regions (white space), and no flicker occurs. Thing is this means twice as much graphic memory is going to be taken up for the buffers (2 buffers instead of 1). So it's not the default functionality of WinForms (though it has been considered by MS to make it default, but then turned down).

But you can turn it on for a parent control. When you create a Control (the Form is a Control, so you can do it to that) you set the style to OptimizedDoubleBuffer:

http://msdn.microsof...y/3t7htc9c.aspx
myForm.SetStyle(ControlStyle.OptimizedDoubleBuffer, True);



Note, if the control you dub the 'parent' is a Form, you may have to set the ControlStyle.ContainerControl style to True as well. Forms are considered containers by default. This allows the draw pass to understand that the draw style pertains to itself and all child controls.

This post has been edited by lordofduct: 23 April 2012 - 10:38 AM

Was This Post Helpful? 1
  • +
  • -

#13 Strezoski777   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 23-April 12

Re: How to avoid creating too many Objects in C#?

Posted 23 April 2012 - 10:37 AM

I don't see any flickering. The labels (Bombas) are falling down without flicker.

The application just slows down when a second or third Bomba appears while another one is falling.

I'm trying the Heartbeat advise at the moment but it doesn't seem to make much of a difference.

I dont know why its lagging so much.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1