0

I am trying to create an application that shows the online trains in picturebox

So to implement this i create a worker thread to get the online train position .so i define the thread as you can see here :

private Thread workerThread = null;
private delegate void UpdateListBoxDelegate();
private UpdateListBoxDelegate UpdateListBox = null;

In Form_load i call these:

            UpdateListBox = new UpdateListBoxDelegate(this.UpdateStatus);
            // Initialise and start worker thread
            workerThread = new Thread(new ThreadStart(this.GetOnlineTrain));
            workerThread.Start();

My method that delegate handles that is :

private void UpdateStatus()
{
    foreach (TimeTable onlineTrain in OnlineTrainList.ToList())
    {
        if (lstSensorLeft.Count != 0 || lstSensorRight.Count != 0)
        {
            pictureBoxonlineTrain.Image = null;

            DrawOnlineTrain();
        }
        else
        {
            pictureBoxonlineTrain.Image = null;
        }
    }

    this.Invalidate();
}

The GetOnlineTrain get the position of online train as you can see here :

public void GetOnlineTrain()
{
    try
    {
        while (true)
        {
            TimeTableRepository objTimeTableREpository = new TimeTableRepository();
            OnlineTrainList = objTimeTableREpository.GetAll().ToList();
            objTimeTableREpository = null;
            Invoke(UpdateListBox);
        }
    }
    catch(Exception a)
    {
    }

}

And the final function draws the online trains on the picturebox :

       public void DrawOnlineTrain()
    {
        Bitmap map;
        using (map = new Bitmap(pictureBoxonlineTrain.Size.Width, pictureBoxonlineTrain.Size.Height))
        {
            if (OnlineTrainList.Count > 0)
            {
                using (Graphics graph = Graphics.FromImage(map))
                {
                    foreach (TimeTable t in OnlineTrainList.ToList())
                    {
                        // graph.Dispose();
                        Rectangle rectTrainState = new Rectangle(t.XTrainLocation.Value - 3,
                                                                 t.YTrainLocation.Value - 3,
                                                                 15, 15);
                        graph.FillRectangle(RedBrush, rectTrainState);
                        graph.DrawString(t.TrainId.ToString(), pictureBoxonlineTrain.Font, Brushes.White, t.XTrainLocation.Value - 3, t.YTrainLocation.Value - 3);
                        pictureBoxonlineTrain.Image = map;

                    }
                }
            }
        }


    }

To draw online train first time i draw the map of trains (lines ,stations ,...) on picturebox with size x=A and y=b after that i create another picturebox with the same size and put the second picturebox on first picturebox using this code:

    pictureBoxonlineTrain.Parent = pictureBoxMetroMap;

But when i run my application in this line i got Parameter is not valid in DrawOnlineTrain .

map = new Bitmap(pictureBoxonlineTrain.Size.Width, pictureBoxonlineTrain.Size.Height);

enter image description here

stack trace:

   at System.Drawing.Image.get_Width()
   at System.Drawing.Image.get_Size()
   at System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMode mode)
   at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180
  • 1
    Have you tried this `new Bitmap(pictureBoxonlineTrain.Width, pictureBoxonlineTrain.Height))` – Hassan Jul 08 '14 at 09:20
  • @HassanNisar i used that in my code – Ehsan Akbar Jul 08 '14 at 09:26
  • 2
    Try removing the `using` from `using (map = ...` - I think the bitmap is being disposed while the picturebox is still trying to paint it. – Blorgbeard Jul 08 '14 at 09:55
  • 1
    You disposed it, careful with applying the *using* statement blindly. – Hans Passant Jul 08 '14 at 09:55
  • @Blorgbeard i removed the using statement before in this question but i got out of memory exception could you please take a look at this :http://stackoverflow.com/questions/24589544/out-of-memory-exception-in-c-sharp-when-drawing-trains-in-picturebox – Ehsan Akbar Jul 08 '14 at 09:59
  • @HansPassant i have to dispose that because of out of memory exception – Ehsan Akbar Jul 08 '14 at 10:00
  • You need to dispose the old bitmap, but only after you've replaced it with a new one. Alternatively, just draw on the same bitmap each time. – Blorgbeard Jul 08 '14 at 10:08

1 Answers1

4

i have to dispose that because of out of memory exception

No, you have to dispose images you don't use any more. Proper code is:

   Bitmap map = new Bitmap(pictureBoxonlineTrain.Size.Width, pictureBoxonlineTrain.Size.Height))
   using (Graphics graph = Graphics.FromImage(map)) {
       graph.Clear(this.BackColor);
       foreach (TimeTable t in OnlineTrainList.ToList()) {
           Rectangle rectTrainState = new Rectangle(...);
           graph.FillRectangle(RedBrush, rectTrainState);
           graph.DrawString(...);
       }
   }
   if (pictureBoxonlineTrain.Image != null) pictureBoxonlineTrain.Image.Dispose();
   pictureBoxonlineTrain.Image = map;
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536