Thread & Repaint problems

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
moelski
Newbie
Newbie
Posts: 6
Joined: Fri Dec 20, 2013 12:00 am

Thread & Repaint problems

Post by moelski » Mon Dec 23, 2013 11:50 am

Hi support,

I just purchased an update of TChart .Net in order to get new access to this forum. I hope spending that money was worth it because i have a big problem with filling a chart from a thread and to repainting.

Demo Appliaction
Ok first of all there is an attached demo application. I tested it with TChart .net version 4.1.2012.01310 and the last November 2013 version which is currently available. Both versions have the same issue.

Problem Description
First of all it is not really clear to me which is thebest way to populate a series data from a thread. My approach was to call an Invoke to the chart, switch off AutoRepaint. Then I add the data to the series. After that I use another Invoke to set back AutoRepaint and do a refresh. Please take a look into my sample and tell me if that is the prefered way.

But the real problem is the repainting of the chart. Start my demo application (I used Visual Studio 2012) and press the button "Start Thread". The thread begins to pupolate the series data. But if you resize the Main Window you got a chart refresh and it starts painting the data even if the thread has not finished!!

In the application I develope the problem also occours if the main Window just loses the focus. This will not "work" in the demo - I don´t know why.

But anyway ... There must be some repaint issues.

So I hope you can answer me these questions:
1) Can you reproduce the repaint problem (even if Repaint is set to false)?
2) Can you fix the Repaint Problem?
3) What is the best way to populate series data from a thread?

I really hope to get some answer from the support team.

Wish you happy christmas and a happy new year.

Dominik
Attachments
ChartRepaint.zip
Demo Application Thread / Repaint
(21.47 KiB) Downloaded 866 times

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Thread & Repaint problems

Post by Christopher » Mon Dec 23, 2013 12:06 pm

moelski wrote: I really hope to get some answer from the support team.
This is a relatively common question, a standard answer to which you can see here.

If the information already posted on these forums about this issue still isn't able to clarify it for you, please don't hesitate to let us know.
moelski wrote: Wish you happy christmas and a happy new year.


Many thanks, and the same to you!
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

moelski
Newbie
Newbie
Posts: 6
Joined: Fri Dec 20, 2013 12:00 am

Re: Thread & Repaint problems

Post by moelski » Mon Dec 23, 2013 12:22 pm

Hi Christopher,

I know these threads. But they don´t helped me a lot. And they only cover the thread Topic.

So please take a look at my demo application. Would be great to know if it is the correct way for threading.
And please take a look at the described repaint Problem.

Thx for your help!

Dominik

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Thread & Repaint problems

Post by Christopher » Mon Dec 23, 2013 12:40 pm

moelski wrote: So please take a look at my demo application. Would be great to know if it is the correct way for threading.
And please take a look at the described repaint Problem.
The problem is is that GDI+ itself is not threadsafe. This is very important to understand. Here is what the MSDN documentation says on the matter:
Thread Synchronization
It is possible for more than one thread to have access to a single GDI+ object. However, GDI+ does not provide any automatic synchronization mechanism. So if two threads in your application have a pointer to the same GDI+ object, it is your responsibility to synchronize access to that object.

Some GDI+ methods return ObjectBusy if a thread attempts to call a method while another thread is executing a method on the same object. Do not try to synchronize access to an object based on the ObjectBusy return value. Instead, each time you access a member or call a method of the object, place the call inside a critical section, or use some other standard synchronization technique.
This means that the ONLY way to make sure TeeChart has finished painting on one thread before it being painted on another thread is to use "a critical section, or some other standard synchronization technique." Does your code use "a critical section, or some other standard synchronization technique"? If it does and you still experience problems, please let me know.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

moelski
Newbie
Newbie
Posts: 6
Joined: Fri Dec 20, 2013 12:00 am

Re: Thread & Repaint problems

Post by moelski » Mon Dec 23, 2013 12:45 pm

Hi Christopher,
Does your code use "a critical section, or some other standard synchronization technique"
No it doesn´t.
Did you see a Chance to modify my attached demo application? It would be a great starting Point and I think some other users would also benefit from that.

So the repaint Problem should disappear if I use such a sync mechanism?

Thx in advance !

Dominik

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Thread & Repaint problems

Post by Christopher » Mon Dec 23, 2013 4:23 pm

moelski wrote: Did you see a Chance to modify my attached demo application? It would be a great starting Point and I think some other users would also benefit from that.

So the repaint Problem should disappear if I use such a sync mechanism?
Yes, it should. Can I please suggest that you start with a simple implementation of such a sync mechanism so you can see for yourself that it works okay?

If you have any problems doing this, please let me know and I'll prepare some example code for you.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

moelski
Newbie
Newbie
Posts: 6
Joined: Fri Dec 20, 2013 12:00 am

Re: Thread & Repaint problems

Post by moelski » Wed Dec 25, 2013 4:29 am

Hi Christopher,

I tried to get it working. Attached you will find my "solution".
But it did not work as expected. If I use a lock as critical section the whole application gets unresponsive.
You can´t move or resize the window ....

So please take a look at this new attachment. It would be really great if you have some advice vor me (us) to get this multithread problem done.

Thx in advance !

Dominik
Attachments
ChartRepaint.zip
With Sync
(17.77 KiB) Downloaded 880 times

moelski
Newbie
Newbie
Posts: 6
Joined: Fri Dec 20, 2013 12:00 am

Re: Thread & Repaint problems

Post by moelski » Thu Dec 26, 2013 6:20 am

Hi Christopher,

there must be an Error in the latest TChart versions. The chart gets repainted if you add values and resize the window.

Here are the steps to reproduce the issue:
* Create a winforms Application (VS 2012 / .net4.0)
* Add a tchart to the Form
* Set the chart Dock Property to Fill
* Add one FastLine
* set the AutpRepaint to false after InitializeComponent();
* Add a timer (and enable it)
* Use this code in the timer event:

Code: Select all

            Random rnd1 = new Random();
            double f1 = rnd1.Next(100000);

            double id = this.tChart1[0].Count + 1;
            this.tChart1[0].Add(id, Math.Sin(id / f1));
Start the Application, resize the Window and your chart repaints :evil:

Btw ... My System is Windows 7 64 Bit. I don´t know if this is an issue.

Anyway ... Please try to reproduce this issue.
Maybe some other users can give it a try, too.

Dominik

Sandra
Site Admin
Site Admin
Posts: 3132
Joined: Fri Nov 07, 2008 12:00 am

Re: Thread & Repaint problems

Post by Sandra » Mon Dec 30, 2013 9:44 am

Hello moleski,

Sorry for the delay. We are working with your problem we will try to give you an answer asap.

Thanks in advance,
Best Regards,
Sandra Pazos / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

moelski
Newbie
Newbie
Posts: 6
Joined: Fri Dec 20, 2013 12:00 am

Re: Thread & Repaint problems

Post by moelski » Tue Dec 31, 2013 6:24 am

Hi Sandra,

great to hear that. If i can assist you with some testing please let me know.

Dominik

moelski.net
Newbie
Newbie
Posts: 19
Joined: Mon Mar 07, 2011 12:00 am

Re: Thread & Repaint problems

Post by moelski.net » Tue Jan 07, 2014 7:01 am

Hi Sandra,

any news on this topic?

Dominik

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Thread & Repaint problems

Post by Christopher » Tue Jan 07, 2014 9:24 am

moelski.net wrote:Hi Sandra,

any news on this topic?

Dominik
Hello :)

Please let me show you what the issue is here, with some simple code you can run on your side (the designtime surface of the Windows Form is empty):

Code: Select all

  public partial class Form3 : Form
  {
    MyTChart tChart1;
    System.Windows.Forms.Panel panel1;

    public Form3()
    {
      InitializeComponent();
      CreateChart();
      InitializeChart();
    }

    private void InitializeChart()
    {
      tChart1.AutoRepaint = false;
      tChart1.Series.Add(typeof(FastLine)).FillSampleValues();
      tChart1.AfterDraw += tChart1_AfterDraw;
    }

    void tChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
    {
      MessageBox.Show("PAINT");
    }

    private void CreateChart()
    {
      panel1 = new System.Windows.Forms.Panel();
      this.Controls.Add(panel1);
      tChart1 = new MyTChart();
      tChart1.Dock = DockStyle.Fill;
      panel1.Dock = DockStyle.Fill;
      panel1.Controls.Add(tChart1);
    }
  }

  public class MyTChart : TChart
  {
    protected override void OnResize(EventArgs e)
    {
      if(AutoRepaint) base.OnResize(e);
    }
  }
The first paint is inevitable, otherwise neither the FastLine series nor any other TeeChart element would be painted. You can check that AutoRepaint=false is working by attempting to zoom the TChart - nothing happens. Now try resizing the form - can you see that the TChart does not resize with the panel1? This is inevitable if we choose not to repaint the chart when resizing it.

So, my question to you is: what would you see as the most logical default behaviour here? That TChart does resize when AutoRepaint=false, as it does now, or that it doesn't?
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

moelski.net
Newbie
Newbie
Posts: 19
Joined: Mon Mar 07, 2011 12:00 am

Re: Thread & Repaint problems

Post by moelski.net » Wed Jan 08, 2014 6:31 am

Hi Christopher,
what would you see as the most logical default behaviour here?
Let me explain what the real problem is in this topic ... It´s not the resising.

As I wrote in my first post we using a thread to populate data to series. And if the chart gets repaint (for example by resizing it) you get in trouble. The GUI threads starts a repaint of the chart (and all series) and the data add thread still appends data to the series.

In order to answer your question ... I think it is not a good idea to avoid the complete resizing while AutoRepaint = false. The best way would be to have a AutoRepaint for series. So the Chart can be resized in any way. But the series will only get painted if you switch back the (Series) Autorepaint.
If the user does a resize while Series AutoRepaint is false it will end with an empty chart. If AutoRepaint for series is set back to true the seriers (with new data) get repainted.

By this way you could ensure that someone adds data to series from a thread and still has an responsive Chart.

What du you think about that?

Dominik

Christopher
Guru
Posts: 1603
Joined: Fri Nov 15, 2002 12:00 am

Re: Thread & Repaint problems

Post by Christopher » Wed Jan 08, 2014 9:08 am

Hello Dominik,
moelski.net wrote: In order to answer your question ... I think it is not a good idea to avoid the complete resizing while AutoRepaint = false.
Okay, good, I agree.
moelski.net wrote: The best way would be to have a AutoRepaint for series. So the Chart can be resized in any way. But the series will only get painted if you switch back the (Series) Autorepaint.
If the user does a resize while Series AutoRepaint is false it will end with an empty chart.
There is a slight problem in this logic. If the series has been painted, that is, if it is visible *before* setting the (hypothetical) Series.AutoRepaint=false then resizing the chart will not give you an empty chart, it will give you a resized chart with an *unresized* series in it. Making the chart empty in this circumstance would mean repainting the series, that is, overwriting the existing pixels with other ones, but by setting Series.AutoRepaint=false it is this that you precisely do not want it to do.

What is more, in an asynchronous painting situation, when you are adding in data to the chart by another thread, disabling series painting using an (hypothetical) Series.AutoRepaint=false is no guarantee that the chart will remain responsive, as other chart elements such as Axes depend on Series algorithms to make their own calculations. As soon as an Axis object tries to query a Series object which is being asynchronously updated, for example, then there is always the danger of the chart becoming unresponsive.

If resizing isn't really the problem, but is just an example of unwanted repainting, then you can always add logic to your code to ensure the chart cannot be resized while is it having data added to it by another thread. With the present TChart.AutoRepaint=false, I cannot think of any other circumstances in which unwanted repainting would occur.
Best Regards,
Christopher Ireland / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Instructions - How to post in this forum

moelski.net
Newbie
Newbie
Posts: 19
Joined: Mon Mar 07, 2011 12:00 am

Re: Thread & Repaint problems

Post by moelski.net » Wed Jan 08, 2014 11:55 am

Hi Christopher,

thx for the explanation.
then you can always add logic to your code to ensure the chart cannot be resized while is it having data added to it by another thread
Well for me it does not work really well.

I took your code example with the Resize Blocking. I´ve added a threaded timer for adding the data. This is what my application basically does.
If you run it you get a strange behaviour. Sometimes you get ghostpictures while resizing. Sometimes each pixel gets painted.
I think that depends on when you start resizing the application window.

Please give it a try. And hopefully you can give me some advise how to make this working better :?

Code: Select all

namespace resize
{
    using System;
    using System.Threading;
    using System.Windows.Forms;

    using Steema.TeeChart;
    using Steema.TeeChart.Styles;

    using Timer = System.Threading.Timer;

    public partial class Form1 : Form
    {
        MyTChart tChart2;
        System.Windows.Forms.Panel panel1;
        public Timer timer;

        public Form1()
        {
            InitializeComponent();
            CreateChart();
            InitializeChart();

            timer = new Timer(this.TimerRun, null, 0, 3000);
        }

        private void InitializeChart()
        {
            tChart2.AutoRepaint = false;
            tChart2.Series.Add(typeof(FastLine));
        }

        private void CreateChart()
        {
            panel1 = new System.Windows.Forms.Panel();
            this.Controls.Add(panel1);
            tChart2 = new MyTChart();
            tChart2.Dock = DockStyle.Fill;
            panel1.Dock = DockStyle.Fill;
            panel1.Controls.Add(tChart2);
        }

        private void TimerRun(object sender)
        {
            var rnd1 = new Random();
            double f1 = rnd1.Next(100000);

            this.tChart2.AutoRepaint = false;
            this.tChart2[0].Clear();
            for (int i = 0; i < 200; i++)
            {
                double id = this.tChart2[0].Count + 1;
                this.tChart2[0].Add(id, Math.Sin(id / f1));
                Thread.Sleep(2);
            }
            
            this.tChart2.AutoRepaint = true;
            this.tChart2.Invalidate();
        }
    }

    public class MyTChart : TChart
    {
        protected override void OnResize(EventArgs e)
        {
            if (AutoRepaint) base.OnResize(e);
        }
    }
}

Post Reply