To be honest, I'm a little bit lame when it comes to threading ;) So I'm asking for a little help.
Let's assume, we have some kind of control on which we can draw some charts. There's also a method that draws a chart on this control. The problem is that the charting method has access only to one of the fields of the control and we need to refresh the control when the chart is ready.
So let's assume our control looks like that:
class ChartingControl : System.Windows.Forms.Control
{
public Canvas canvas;
public void Refresh();
/*
... other fields/methods
*/
}
where Canvas
is a class used to draw the image (something like Graphics).
The charting method has access only to the canvas
object (we cannot change it), so it looks like that:
public static void DrawChart(canvas)
{ /* draw */ }
This method can be called from a separate thread, background worker etc... And I need to synchronize it with the main thread and call Refresh()
when the chart is ready.
Right now when the chart is ready, I set a flag on canvas object
public static void DrawChart(canvas)
{ /* draw */
canvas.Tag = true; // chart is ready
}
And I have a background worker running inside of the charting control and listening if the canvas.Tag
field has changed and if so, it calls Refresh()
But it seems that my method is a little bit rought, easy-to-fail etc... Is there any better method to improve it?
Limitations:
- we cannot modify Canvas
class. The only thing we can use is the Tag
field (of type object
- we can modify ChartingControl
class and drawing method.
- There can be many charting controls
- We have no control over how DrawChart
is called. It can be called in a separate thread, or not. It is called elsewhere. All we can do is to create the control and the DrawChart method and try to comunicate them somehow
Solution
OK, I solved it this way: in ChartingControl
I created a ManualResetEvent manualReset
and a background worker.
Bacground worker waits for the manualReset
:
void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
manualReset.WaitOne(); // Wait for a chart to be ready
}
and in the end calls Reset() method
void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
Refresh();
}
I pass the manualReset
object inside canvas.Tag
and inside drawing method, when the chart is ready I call manualReset.Set();
to pass the signal that chart is ready.