In the example code below, we attach two RenderableSeries to a single SciChartSurface.
The first RenderableSeries adds data from surface.suspendUpdates, and the second RenderableSeries adds data from setVisibleRangeChangeListener, which causes the chart to freeze.
The chart freezes even when I take actions such as using suspendUpdates in setVisibleRangeChangeListener, or adding data after performing a check such as Axis.isAttached.
However, if I run the code related to the dataSeries in the main thread, as shown in the code, the freezing goes away. Is this the correct way to perform changes to the dataSeries in the setVisibleRangeChangeListener?
import android.view.View
import com.scichart.charting.Direction2D
import com.scichart.charting.modifiers.AxisDragModifierBase
import com.scichart.charting.visuals.SciChartSurface
import com.scichart.charting.visuals.axes.AutoRange
import com.scichart.charting.visuals.axes.AxisAlignment
import com.scichart.charting.visuals.renderableSeries.FastCandlestickRenderableSeries
import com.scichart.core.model.DateValues
import com.scichart.core.model.DoubleValues
import com.scichart.data.model.DoubleRange
import com.scichart.examples.utils.scichartExtensions.OhlcDataSeries
import com.scichart.examples.utils.scichartExtensions.XyDataSeries
import com.scichart.examples.utils.scichartExtensions.categoryDateAxis
import com.scichart.examples.utils.scichartExtensions.chartModifiers
import com.scichart.examples.utils.scichartExtensions.fastColumnRenderableSeries
import com.scichart.examples.utils.scichartExtensions.numericAxis
import com.scichart.examples.utils.scichartExtensions.pinchZoomModifier
import com.scichart.examples.utils.scichartExtensions.renderableSeries
import com.scichart.examples.utils.scichartExtensions.rolloverModifier
import com.scichart.examples.utils.scichartExtensions.suspendUpdates
import com.scichart.examples.utils.scichartExtensions.xAxes
import com.scichart.examples.utils.scichartExtensions.xAxisDragModifier
import com.scichart.examples.utils.scichartExtensions.yAxes
import com.scichart.examples.utils.scichartExtensions.zoomPanModifier
import java.util.Date
fun initSampleCode(surface: SciChartSurface, ) {
surface.suspendUpdates {
val ohlcDataSeries = OhlcDataSeries<Date, Double>()
val ohlcRenderableSeries = FastCandlestickRenderableSeries().apply {
dataSeries = ohlcDataSeries
}
val volumeDataSeries = XyDataSeries<Double, Double>("volume series")
val sharedYRange = DoubleRange(0.0, 10.0)
val volumeProfileXRange = DoubleRange(0.0, 10.0)
renderableSeries {
fastColumnRenderableSeries {
dataSeries = volumeDataSeries
xAxisId = "column-xAxis"
yAxisId = "column-yAxis"
dataPointWidth = 1.0
}
add(ohlcRenderableSeries)
}
xAxes {
// 캔들
categoryDateAxis {
// axisId = "date-xAxis"
cursorTextFormatting = "yyyy.MM"
textFormatting = "yyyy.MM"
setVisibleRangeChangeListener { axis, oldRange, newRange, isAnimate ->
val columnYDoubleValues = DoubleValues()
columnYDoubleValues.add(1.0)
columnYDoubleValues.add(2.0)
columnYDoubleValues.add(3.0)
columnYDoubleValues.add(4.0)
columnYDoubleValues.add(5.0)
columnYDoubleValues.add(6.0)
columnYDoubleValues.add(7.0)
columnYDoubleValues.add(8.0)
columnYDoubleValues.add(9.0)
columnYDoubleValues.add(10.0)
val columnXDoubleValues = DoubleValues()
columnXDoubleValues.add(725_000.0)
columnXDoubleValues.add(736_000.0)
columnXDoubleValues.add(747_000.0)
columnXDoubleValues.add(758_000.0)
columnXDoubleValues.add(769_000.0)
columnXDoubleValues.add(770_000.0)
columnXDoubleValues.add(781_000.0)
columnXDoubleValues.add(792_000.0)
columnXDoubleValues.add(803_000.0)
// !!CHART FREEZED!!
volumeDataSeries.clear()
volumeDataSeries.append(columnXDoubleValues, columnYDoubleValues)
// NOT FREEZED
// CoroutineScope(Dispatchers.Main).launch {
// volumeDataSeries.clear()
// volumeDataSeries.append(columnXDoubleValues, columnYDoubleValues)
// }
}
}
numericAxis {
axisId = "column-xAxis"
autoRange = AutoRange.Never
axisAlignment = AxisAlignment.Right
visibility = View.GONE
this.flipCoordinates = true
visibleRange = sharedYRange
}
}
yAxes {
numericAxis {
// axisId = "price-yAxis"
autoRange = AutoRange.Always
growBy = DoubleRange(0.2, 0.2)
cursorTextFormatting = "###,###"
textFormatting = "###,###"
visibleRange = sharedYRange
}
numericAxis {
axisId = "column-yAxis"
axisAlignment = AxisAlignment.Bottom
// visibility = View.GONE
visibleRange = volumeProfileXRange
}
}
chartModifiers {
xAxisDragModifier {
receiveHandledEvents = true
dragMode = AxisDragModifierBase.AxisDragMode.Pan
}
pinchZoomModifier {
receiveHandledEvents = true
direction = Direction2D.XDirection
}
zoomPanModifier {
receiveHandledEvents = true
}
rolloverModifier()
}
val sampleDateValues = DateValues()
sampleDateValues.add(
arrayOf(
Date(1388070000000),
Date(1388156400000),
Date(1388242800000),
Date(1388329200000),
Date(1388415600000),
Date(1388502000000),
Date(1388588400000),
Date(1388674800000),
Date(1388761200000),
)
)
val sampleOpenValues = DoubleValues()
sampleOpenValues.add(
doubleArrayOf(
737000.0,
750000.0,
750000.0,
740000.0,
768000.0,
768000.0,
776000.0,
778000.0,
831000.0,
)
)
val sampleHighValues = DoubleValues()
sampleHighValues.add(
doubleArrayOf(
755000.0,
750000.0,
750000.0,
772000.0,
800000.0,
795000.0,
788000.0,
840000.0,
846000.0
)
)
val sampleLowValues = DoubleValues()
sampleLowValues.add(
doubleArrayOf(
737000.0,
750000.0,
728000.0,
740000.0,
763000.0,
765000.0,
773000.0,
774000.0,
819000.0,
)
)
val sampleCloseValues = DoubleValues()
sampleCloseValues.add(
doubleArrayOf(
755000.0,
750000.0,
739000.0,
768000.0,
768000.0,
777000.0,
778000.0,
834000.0,
846000.0
)
)
ohlcDataSeries.clear()
ohlcDataSeries.append(sampleDateValues, sampleOpenValues, sampleHighValues, sampleLowValues, sampleCloseValues)
}
}
- JAIHOON PARK asked 11 months ago
- last edited 11 months ago
- You must login to post comments
Hi there,
The above code doesn’t look like a good idea. You are suspending a chart using SciChartSurface.suspendUpdates()
. This freezes redrawing and also has a thread-synchronization lock in it to ensure that it’s thread safe when suspending/resuming from different threads.
Later in the axis.setVisibleRangeChangeListener
callback you are modifying data. When you try to modify data we will be checking if the chart is suspended and also checking locks.
So – it’s likely that your code is causing a deadlock.
What we recommend:
- Don’t ever update data directly inside a
setVisibleRangeChangeListener
callback. This will trigger another redraw and could cause infinite recursion. If you need to update your data on zoom, I suggest decoupling from thesetVisibleRangeChangeListener
callback by using some kind of pub/sub mechanism - If you call
suspendUpdates
be aware that calling suspend/resume or updating data from different threads can cause at best thread-contention, and at worst, a deadlock
- Andrew Burnett-Thompson answered 11 months ago
- You must login to post comments
Please login first to submit.