Need Pattern to Update Chart Every 5 Ms from the ViewModel Which Is In a Separate Library Project

Hi,

I need help finding a pattern to update a bound SfChart. The challenge is that the view model exists in a Library because it has to be accessible to various UI frameworks. Not just WPF.


Here is the scenario. I have a class that is running on a worker thread that is loading lists of price data. In the view model, I want to update the ObservableCollections with this price data, so that it is reflected in the bound chart. I have to update the collections every 5ms, because if I just update at full speed, the UI will be frozen.


I had come up with 1 pattern using System.Timers.Timer, setting its interval to 5ms, and then in the Elapsed event, I am using SynchronizationContext to call the code that syncs the ObservableCollection to the lists of price data.


This worked when I tested without a syncfusion control. But when I bind to the chart, and try to use this approach. the UI runs for about 5 seconds and then freezes.


Everything works fine if I use the DispatcherTimer in the codebehind. But like I said, I need to do the syncing in the view model, because it has to be accessible to different UI frameworks.


I have attached some sample code to reproduce the problem (it is part of a larger project so I just included the specific files).

You can switch back and forth to see both types of behavior by flipping the if statement in the code behind, in line 37.


Could someone advise if there is a way to make this work?


Thanks


20 Replies

LO Lorenzo June 17, 2022 01:19 AM UTC

Reattaching files here with small adjustment.


Attachment: RefreshChartWithSyncedWorkerThreadData_d48260a7.zip


DD Devakumar Dhanapoosanam Syncfusion Team June 17, 2022 01:45 PM UTC

Hi Lorenzo,


We will validate and update complete details in two business days on or before June 21, 2022.


Regards,

Devakumar D



DD Devakumar Dhanapoosanam Syncfusion Team June 22, 2022 03:29 AM UTC

Hi Lorenzo,


We were able to reproduce the reported problem with the provided code file, and we still need some more time to validate this with our development team and we will update further details on June 23, 2022.


Regards,

Devakumar D



DD Devakumar Dhanapoosanam Syncfusion Team June 27, 2022 05:45 AM UTC

Hi Lorenzo,


Sorry for the delay.


The reported issue occurs only when using Timer in view model and updating using different thread, causing the UI freeze after a few seconds. Due to difficulty, we still need some more time with our development to find the exact root cause and will update further details on June 28, 2022.


Also, UI freeze occurs only while updating the view model Bars ObservableCollection data by replacing the existing data item using SynchronizationContext in the sync method and we have commented out then chart update proper as in below code.


ViewModel.cs

public void Sync()

{

    int startIx = Bars.Count == 0 ? 0 : Bars.Count - 1;

 

    for (int i = startIx; i < _class.Bars.Count; i++)

    {

        if (Bars.Count == 0 || i > Bars.Count - 1)

        {

            Bars.Add(_class.Bars[i].Clone());

        }

        else

        {

            Bars[i] = _class.Bars[i].Clone();

        }

    }
   

}


Regards,

Devakumar D



LO Lorenzo June 27, 2022 10:11 AM UTC

Hi,


Thank you I will await the next response. I need to be able to update the bar, to represent a tick within the same bar.



DD Devakumar Dhanapoosanam Syncfusion Team June 29, 2022 06:47 AM UTC

Hi Lorenzo,


On further analysis with the development team, we can resolve this while updating chart data collection using viewmodel Timer causing UI freeze by using the Dispatcher as per the below code example.


private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)

{

    var application = Application.Current;

    if (application != null)

    {

        application.Dispatcher.BeginInvoke(

           new Action(() =>

           {

               Sync();

           }),

           DispatcherPriority.Background,

           null

       );

    }

}


And we need to stop the view model timer as per in below code.


protected override void OnDeactivated(EventArgs e)

{

    base.OnDeactivated(e);

    if (_vm != null && _vm.Running)

    {

        _vm.StopSyncingUsingSynchronizationContext();

    }

}


Please find the modified sample from the attachment below and let us know if you need any further assistance.


Regards,

Devakumar D


Attachment: SF_175692_97270475.zip


LO Lorenzo June 29, 2022 10:06 AM UTC

Hi Devakumar,


I'm sorry but this solution will not work. As I stated in my original message...

The challenge is that the view model exists in a Library because it has to be accessible to various UI frameworks


The view model is not in the WPF project, since the code is in a library it does not have access to System.Windows.Threading, and therefore the Dispatcher cannot be used (this is to the best of my knowledge, and if you know of a way to access System.Windows.Threading, please let me know)


Apologies if there was miscommunication, but I thought I had made that clear at the start.


I've attached a new version of the solution, where the viewmodel is separated into a class library. And the WPF startup project references this library.







Attachment: SampleLibrary_38defac7.zip



DD Devakumar Dhanapoosanam Syncfusion Team July 1, 2022 04:12 AM UTC

Hi Lorenzo,


Sorry for the inconvenience caused.


We have forwarded this to our development team, and we will update further details in two business days on July 4, 2022.


Regards,

Devakumar D



LO Lorenzo July 8, 2022 11:20 AM UTC

Hi Devakumar,


Just following up.

Has any progress been made?


Thanks,

Lorenzo



LO Lorenzo July 12, 2022 11:12 AM UTC

Hi Devakumar,


Following up again as I've heard nothing.


Thanks,

Lorenzo



DD Devakumar Dhanapoosanam Syncfusion Team July 13, 2022 02:46 AM UTC

Hi Lorenzo,


We deeply regret for the delay. We are working on this with high priority, and still we need some more time to validate this issue. We will update further details on July 14, 2022. We appreciate your patience until then.


Regards,

Devakumar D



LO Lorenzo July 18, 2022 10:40 AM UTC

Hi  Devakumar,

Following up again to see if you have any more information?


Lorenzo



DD Devakumar Dhanapoosanam Syncfusion Team July 19, 2022 01:03 PM UTC

Hi Lorenzo,


Sorry for the delay.


We would like to suggest using DateTimeAxis as chart primary axis instead of CategoryAxis, with huge data using category axis affects chart performance and remove the Interval property of axis as per in the below code example.


<chart:SfChart.PrimaryAxis>

    <chart:DateTimeAxis x:Name="xAxis"

                        EnableScrollBar="True"

                        ShowTrackBallInfo="True"

                        LabelFormat="d MMM HH:mm"

                        ZoomFactor ="{Binding Path=XZoomFactor, Mode=TwoWay}"

                        ZoomPosition ="{Binding Path=XZoomPosition, Mode=TwoWay}"/>

</chart:SfChart.PrimaryAxis>


We can resolve this by removing the Timer which causes UI to freeze while updating. Instead, we would like to suggest using Task.Delay for every 5ms delay as per in the below code example to update chart.


public static class TimerTask

{

    public static async Task Run(Action action, TimeSpan period, CancellationToken cancellationToken)

    {

        while (!cancellationToken.IsCancellationRequested)

        {

            await Task.Delay(period, cancellationToken);

 

            if (!cancellationToken.IsCancellationRequested)

                action();

        }

    }

}

public void StartSyncingUsingSynchronizationContext()

{

    _class.Start();

    source = new CancellationTokenSource();

    Constants.UiContext!.Post((state) =>

    {

        task = TimerTask.Run(Sync, new TimeSpan(0, 0, 0, 0, 5), source.Token);

    }, null);f

}


Please find the sample in the attachment below and let us know if you need any further assistance.


Regards,

Devakumar D


Attachment: SampleLibraryModified_8b09dd5e.zip


LO Lorenzo July 19, 2022 05:01 PM UTC

Hi Devakumar,

The sample you attached does not work.


1 - Using DateTimeAxis results in bars being written all over each other (screenshot attached)

2 - the chart still crashes. It will sometimes get to 100-200 candles. but it always gets choppy performance and then freezes.


Attachment: ChartWithDateTimeAxis_5511375f.zip


DD Devakumar Dhanapoosanam Syncfusion Team July 20, 2022 02:06 PM UTC

Hi Lorenzo,


We were able to reproduce the reported problem using DateTimeAxis at our end, we will validate and update the complete details on July 21, 2022.


Regards,

Devakumar D



LO Lorenzo July 20, 2022 03:58 PM UTC

Thank you but please be aware the biggest issue is still that the chart crashes.



DD Devakumar Dhanapoosanam Syncfusion Team July 21, 2022 02:19 PM UTC

Hi Lorenzo,


We have confirmed the reported problem “DateTimeAxis range does not update properly and segments overlap with each other in real time update” as an issue and the fix for the reported issue will be included in our upcoming 2022 Volume 2 SP release which is scheduled to roll out on second week of August, 2022. We will let you know once it gets rolled out.


Feedback: https://www.syncfusion.com/feedback/36495


Note: The provided feedback link is private, and you need to login to view this feedback.


And we still need some more time to validate the chart UI freezing/crashes issue with our development team and we will update details in two business day on July 25, 2022. We appreciate your patience until then.


Regards,

Devakumar D



LO Lorenzo July 28, 2022 10:02 AM UTC

Hello,

Following up again to see if there is an update.



LO Lorenzo July 31, 2022 10:26 PM UTC

I understand that this is a complex problem. But it has been a month and a half... Curious to know if the developers have been making any progress? 



DD Devakumar Dhanapoosanam Syncfusion Team August 1, 2022 01:18 PM UTC

Hi Lorenzo,


We deeply regret for the delay.


We would like to let you know that while checking the same sample in release mode, the live update chart performance improved, and real time update was working properly without freezing the UI after removing the chart data replace code in the view model Sync method instead remove and update the new data as per in below code example and disable the chart series tooltip.


public void Sync()

{

    int startIx = Bars.Count == 0 ? 0 : Bars.Count - 1;

 

    for (int i = startIx; i < _class.Bars.Count; i++)

    {

        if (Bars.Count == 0 || i > Bars.Count - 1)

        {

            Bars.Add(_class.Bars[i].Clone());

        }

        else

        {

            if (Bars.Count - 1 <= i)

            {

                Bars.RemoveAt(i);

                Bars.Insert(i, _class.Bars[i].Clone());

            }        

        }

    }

   

}


Please find the tested sample and video in the attachment below.


Could you please check with the above suggested solution in release mode and let us know if you face any problem?


Regards,

Devakumar D


Attachment: SF_175692_SampleLibrary_9198b87a.zip

Loader.
Up arrow icon