I have a windows form which has 1 button (for simplicity).
On clicking this button, I start an algorithm in a separate background thread using ParameterizedThreadStart.
Now this algorithm produces output at regular time intervals which needs to be displayed in a chart.
If i init the chart in MainForm and pass this object to algorithm thread, then it doesnt allow and says chart's allocation and access are cross-thread.
If i have chart object inside algo class, then it doesnt display the chart ticks. Only a blank form shows up (that too by doing _chart.Show()) and no ticks displayed.
Also, how to AddPoint to the chart, I used chart.Invoke(chart.AddPointDelegate, params) in the 2nd case, but it gets stuck at Invoke.
Please help me with a way out.
EDIT:
public MyForm()
{
InitializeComponent();
_getChartDataDelegate = AddTickToChart;
}
public AddTickChartDelegate _getChartDataDelegate;
public void AddTickToChart(ChartTickPoint point)
{
DateTime x = point.X;
double y = point.Y;
object[] parameters = { x, y };
if (this.InvokeRequired)
{// this prevents the invoke loop
this.Invoke(new Action<ChartTickPoint>(_chart.chartDelegate), new object[] { point }); // invoke call for _THIS_ function to execute on the UI thread
}
else
{
//function logic to actually add the datapoint goes here
//_chart.Invoke(_chart.chartDelegate, parameters);
_chart.AddTick(point);
}
}
private void button_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ParameterizedThreadStart(MyUtils.RunAlgo));
AlgoData algoData = new AlgoData(myFile, _getChartDataDelegate);
thread.Start(algoData);
}
// MyForm ends
// Intermediate static Util class to run algo
MyUtils.RunAlgo(object obj)
{
// new Algo
// Get delegate from algoData obj
algo.Run(delegateInTheMyForm);
}
// Algo class's Run
Run(AddTickChartDelegate delegateInTheMyForm)
{
delegateInTheMyForm(point);
}
// Chart class
public AddTickChartDelegate chartDelegate;
public void AddTick(ChartTickPoint point)
{
DateTime timeStamp = point.X;
double y = point.Y;
foreach (Series ptSeries in chart1.Series)
{
AddNewPoint(timeStamp, y, ptSeries);
}
}
Here again i am getting cross-thread issue at this.Invoke(new Action..) in MyForm class.
Further,
If i replace this.Invoke(Action..) with chart.Invoke(..)
if (this.InvokeRequired)
{
_chart.Invoke(_chart.chartDelegate, point);
// instead of Action...
}
then it goes through , but the chart form is not responsive and is blank.
Write a function for adding datapoints in your form class
For example:
You can call this function from your worker thread since it will invoke the UI thread to avoid cross-thread access
So... yes, your worker will need to have a reference to that function... if you want to keep your algo class knowledge of the form to a minimum, you can build an object that holds the reference to the form (cast to ISynchronizedInvoke) and the delegate (addDataPoint) so the worker keeps separated from the UI.
//EDIT: Complete example Form