Thread & Repaint problems
Thread & Repaint problems
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
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 918 times
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Thread & Repaint problems
This is a relatively common question, a standard answer to which you can see here.moelski wrote: I really hope to get some answer from the support team.
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 |
Re: Thread & Repaint problems
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
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
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Thread & Repaint problems
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: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.
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.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.
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 |
Re: Thread & Repaint problems
Hi Christopher,
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
No it doesn´t.Does your code use "a critical section, or some other standard synchronization technique"
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
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Thread & Repaint problems
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?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?
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 |
Re: Thread & Repaint problems
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
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 913 times
Re: Thread & Repaint problems
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:
Start the Application, resize the Window and your chart repaints
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
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));
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
Re: Thread & Repaint problems
Hello moleski,
Sorry for the delay. We are working with your problem we will try to give you an answer asap.
Thanks in advance,
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 |
Instructions - How to post in this forum |
Re: Thread & Repaint problems
Hi Sandra,
great to hear that. If i can assist you with some testing please let me know.
Dominik
great to hear that. If i can assist you with some testing please let me know.
Dominik
-
- Newbie
- Posts: 19
- Joined: Mon Mar 07, 2011 12:00 am
Re: Thread & Repaint problems
Hi Sandra,
any news on this topic?
Dominik
any news on this topic?
Dominik
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Thread & Repaint problems
Hellomoelski.net wrote:Hi Sandra,
any news on this topic?
Dominik
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);
}
}
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 |
-
- Newbie
- Posts: 19
- Joined: Mon Mar 07, 2011 12:00 am
Re: Thread & Repaint problems
Hi Christopher,
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
Let me explain what the real problem is in this topic ... It´s not the resising.what would you see as the most logical default behaviour here?
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
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: Thread & Repaint problems
Hello Dominik,
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.
Okay, good, I agree.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.
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.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.
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 |
-
- Newbie
- Posts: 19
- Joined: Mon Mar 07, 2011 12:00 am
Re: Thread & Repaint problems
Hi Christopher,
thx for the explanation.
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
thx for the explanation.
Well for me it does not work really well.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
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);
}
}
}