Exception when changing MDIParent with TeeChart

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Post Reply
dimitrig
Newbie
Newbie
Posts: 17
Joined: Wed Jul 18, 2007 12:00 am
Location: Belgium
Contact:

Exception when changing MDIParent with TeeChart

Post by dimitrig » Thu Mar 04, 2010 12:23 pm

Hi,

I have a problem with TeeChart v3. Currently I'm using version 3.5.3498.27367. I assume it will also be a problem in the newer v3 version and/or version 2009. You can download a demonstrator project from my webspace http://users.edpnet.be/avathar/NMDG/Tee ... 20Form.zip and compile for yourself.

The problem is that some exception is generated from deep down in the drawing routines of TeeChart. When you have a form with a TeeChart on it (in my example called TeeChartForm), and you dare to change the MDIParent while the form is visible, you'll get the following exception:

Code: Select all

System.ArgumentException: Parameter is not valid.
   at System.Drawing.Graphics.GetHdc()
   at System.Drawing.BufferedGraphics.Render(Graphics target)
   at System.Drawing.BufferedGraphics.Render()
   at Steema.TeeChart.TChart.OnPaint(PaintEventArgs pe)
   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
   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.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
We do this to dock/undock forms from an MDI interface (in my example the MainForm is the MDI).

Just run the example. First you will just see an empty form in the MDI. Through the Tools menu you can dock/undock the form. You will see that everything works fine until then.
Then through the Tools menu you can make the TeeChart component visible. Now try to dock/undock, and you will see the exception.

We have not seen a similar problem with forms with other controls on it. We have tested a lot of complex forms with all kind of controls on it, and none of them gave any problem. So the problem is not coming from the .NET framework drawing engine, but specifically from the TeeChart component and when you use that one.

I already used the OnPaint method to hook into the drawing and monitor some of the parameters, but at this moment I was not able to catch where the problem comes from.

FYI... I'm using Visual Studio 2005 and .NET framework 2.0 SP2.

kind regards,
Dimitri

Yeray
Site Admin
Site Admin
Posts: 8876
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by Yeray » Fri Mar 05, 2010 3:30 pm

Hi Dimitri,

I've reproduced the problem in VS2008 and the latest TeeChart but it works fine if you set:

Code: Select all

_tForm.tChart1.Graphics3D.BufferStyle = Steema.TeeChart.Drawing.BufferStyle.None;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

dimitrig
Newbie
Newbie
Posts: 17
Joined: Wed Jul 18, 2007 12:00 am
Location: Belgium
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by dimitrig » Fri Mar 05, 2010 4:01 pm

Hi Yeray,

You are correct that this removes the exception.

Now, I do not want to disable buffering, since this will cause other side-effects in my graph I assume (e.g. slower drawing and/or flickering). We are using this in a real-time application with lots of charts and lots of data points and cursors etc... so I guess disabling the buffer is not a solution for us. So while it is ok for the demo app, I hope you can fix this without having to disable the buffering in a future release of TeeChart ;o).

regards,
Dimitri

Yeray
Site Admin
Site Admin
Posts: 8876
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by Yeray » Fri Mar 05, 2010 4:59 pm

Hi Dimitri,

What about DoubleBuffer? It seems to work fine here too.

Code: Select all

_tForm.tChart1.Graphics3D.BufferStyle = Steema.TeeChart.Drawing.BufferStyle.DoubleBuffer;
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

dimitrig
Newbie
Newbie
Posts: 17
Joined: Wed Jul 18, 2007 12:00 am
Location: Belgium
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by dimitrig » Fri Mar 05, 2010 6:41 pm

Hi Yeray,

You are correct again, but it still is a performance killer if we do this.

We have a test application to monitor the speed of the charts (plotting several plot updates with 1M points and more). If I run this speed test with the optimized buffer of TeeChart, it does it in 8.5 sec, which is the expected order of magnitude for that test (monitoring the perfomance over time with each TeeChart update, because we want to keep a close eye on the perfomance of our charts). Now when I set this to the proposed double buffer of the .NET framework, the test app does it in 16 sec. So that is a perfomance drop of almost a factor 2, which isn't acceptable for us (since we have a real-time app).

So it looks like the bug (exception) is indeed originating from the fact that the TeeChart optimized buffer is used. However I am unable to disable this buffer, since this will kill the performance. So I still hope that somebody can fix this bug when the optimized buffer is used.

Btw... it seems to have some relation to some other bug I reported: http://www.teechart.net/support/viewtop ... =4&t=10471. This bug is still manifesting itself in our app, which blocks us from upgrading TeeChart any further. I got response from you guys that you couldn't reproduce it, while every time I run it (open the app and then maximize the form), I hit the problem. Also with the latest release that I installed just today 3.5.3700.30575. Now when I go to the DoubleBuffer there as well, that problem is also gone.

kind regards,
Dimitri

Yeray
Site Admin
Site Admin
Posts: 8876
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by Yeray » Wed Mar 10, 2010 10:16 am

Hi Dimitri,

I'm afraid we can't consider this as a TeeChart related problem because this type of buffer is the one designed by Microsoft to work with MDI forms.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

dimitrig
Newbie
Newbie
Posts: 17
Joined: Wed Jul 18, 2007 12:00 am
Location: Belgium
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by dimitrig » Wed Mar 10, 2010 11:40 am

Hi Yeray,

I think you possibly misunderstood me. As far as I can see it is the TeeChart buffer that is causing this.

When I use the integrated windows buffers, I have no exceptions and there is no problem. So they don't have the problem.

When I use the TeeChart buffer (the one your company specifically developed), I have exceptions. We want to use this buffer however, since it is the most performant one, and the one we have been using for years.

Here is the stacktrace again:

Code: Select all

System.ArgumentException: Parameter is not valid.
   at System.Drawing.Graphics.GetHdc()
   at System.Drawing.BufferedGraphics.Render(Graphics target)
   at System.Drawing.BufferedGraphics.Render()
   at Steema.TeeChart.TChart.OnPaint(PaintEventArgs pe)
   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
   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.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
When I went into the GetHdc method with debugger, using the source of the .NET framework which is available now, I get this:

Code: Select all

public IntPtr GetHdc() { 
            IntPtr hdc = IntPtr.Zero;
 
            int status = SafeNativeMethods.Gdip.GdipGetDC(new HandleRef(this, this.NativeGraphics), out hdc); 

            if (status != SafeNativeMethods.Gdip.Ok) { 
                throw SafeNativeMethods.Gdip.StatusException(status);
            }

            this.nativeHdc = hdc; // need to cache the hdc to be able to release with a call to IDeviceContext.ReleaseHdc(). 

            return this.nativeHdc; 
        }
The status you get there is invalid, and this causes the parameter exception.

So I'm not stating that the exception is coming from within TeeChart's code. But my guess is that TeeChart is setting some parameters in this scenario which causes the normal drawing to throw exceptions. Apparently these parameters are only set to an erroneous state, when you use the TeeChart buffer.

So while I understand that this is a complex thing to investigate and debug, it still looks to me that there is something in the TeeChart's buffer that is causing this. I have not seen any problems with any other controls that we use (we use plenty of windows forms controls from 3rd parties etc). So we only have this problem when we use TeeChart, and when we set it on the optimized TeeChart buffer.

Btw... I only have the problem when I change the MDIParent while the TeeChart is showing. There is no problem to show a TeeChart on a form in an MDI, so there is nothing wrong with using TeeChart in an MDI scenario. It is only when you switch this MDIParent on-the-fly (e.g. make it null, to undock it from the MDI), that the exeption is thrown.

kind regards,
Dimitri

Christopher
Site Admin
Site Admin
Posts: 1349
Joined: Thu Jan 01, 1970 12:00 am
Location: Riudellots de la Selva, Catalonia
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by Christopher » Thu Mar 11, 2010 9:44 am

Dimitri,

Thank you very much for your all your input on this issue.

TeeChart's OptimizedBuffer is based on the standard .net technique outlined here:
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

it seems that of all the windows forms controls you use, TeeChart is the only one with this technique implemented.

Unfortunately, the only way I've found to fix this problem when setting MdiParent to null reduces performance to below that of DoubleBuffer. If you open TeeChart.dll in Reflector, I'll explain what I mean. Have a look at the Steema.TeeChart.TChart.OnPaint method. Here you can see that if the BackBuffer property, of type BufferedGraphics, is null, a new one is allocated. It is allocating this only once for the lifetime of an instance of TChart that causes the performance gains. Now, setting MdiParent to null causes Chart.Graphics3D.BackBuffer.Graphics.GetHdc() to have an invalid value. Note that this means that GetHdc() actually *does* return a value, the value is *not* IntPtr.Zero, but the value is invalid. Therefore there is no way for the TeeChart code to check if this pointer is valid or not. The only way to work around the problem would be to allocate the BackBuffer on every paint, which works fine but which reduces performance dramatically.

It is for this reason that we recommend the use of DoubleBuffer when using TChart in a Mdi application when setting MdiParent to null unless, of course, you are prepared to set the BackBuffer to null every time you switch MdiParent, e.g.

Code: Select all

        private void switchToolStripMenuItem_Click(object sender, EventArgs e)
        {
          _tForm.tChart1.Graphics3D.BackBuffer = null;
          if (_tForm.MdiParent == this)
            _tForm.MdiParent = null;
          else
            _tForm.MdiParent = this;
          _tForm.Show();
        }
Thank you!

Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/

dimitrig
Newbie
Newbie
Posts: 17
Joined: Wed Jul 18, 2007 12:00 am
Location: Belgium
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by dimitrig » Thu Mar 11, 2010 10:34 am

Hi Christopher,

Thanks for the explanation about this part. I now get where the problem is coming from, and what my options are.

I have inherited from TChart with my own class, and I can override the OnPaint method. In that method I will cache the MDIParent. When I see that it has changed, I will clear the back buffer. So I think that is a solution for me, and then I can keep using the optimized buffer.

Are there other scenarios that you guys know of that you have to be careful with when using the optimized buffer?
Is it OK to keep using the optimized buffer in an MDI, on condition that the MDI parent does not change of course, or are there other known side-effects that you need to be careful with?
We just want to keep the optimized buffer if we can (since performance is our number #1 priority), but maybe you can warn me for some other side-effects ;o).

kind regards,
Dimitri

Christopher
Site Admin
Site Admin
Posts: 1349
Joined: Thu Jan 01, 1970 12:00 am
Location: Riudellots de la Selva, Catalonia
Contact:

Re: Exception when changing MDIParent with TeeChart

Post by Christopher » Thu Mar 11, 2010 11:33 am

Dimitri,
dimitrig wrote: Are there other scenarios that you guys know of that you have to be careful with when using the optimized buffer?
No, not that we are aware of.
dimitrig wrote: Is it OK to keep using the optimized buffer in an MDI, on condition that the MDI parent does not change of course, or are there other known side-effects that you need to be careful with?
Again no, we are not aware of any other unwanted effects.
dimitrig wrote: We just want to keep the optimized buffer if we can (since performance is our number #1 priority), but maybe you can warn me for some other side-effects ;o).
Of course, I quite understand. The only time we have found that the hDC pointer changes during the lifetime of a TChart instance is when the MdiParent is changed. We are not presently aware of any other complications.
Thank you!

Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/

Post Reply