This is a migrated thread and some comments may be shown as answers.

chart in multiple view

11 Answers 220 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Rodolfo
Top achievements
Rank 1
Rodolfo asked on 24 Jul 2019, 10:07 PM

I am trying to use the chart control in multiple views: Meaning not just one window. I create several windows from the main windows. It is not call "windows". It is views.

It looks like the chart control fails:

 

System.Exception: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
   at Windows.UI.Xaml.Media.SolidColorBrush.get_Color()
   at Telerik.UI.Xaml.Controls.Chart.ContainerVisualsFactory.ChangeBrushesAccordingToAppTheme()
   at Telerik.UI.Xaml.Controls.Chart.ContainerVisualsFactory.PrepareCartesianAxisLineVisual(CartesianAxis axis, ContainerVisual lineContainer, RadRect layoutSlot, AxisType axisType)
   at Telerik.UI.X

 

Is there a way to fix it ?

 

to understand the concept of multiple views:

 

https://docs.microsoft.com/en-us/windows/uwp/design/layout/show-multiple-views

 

please advise me...

11 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 24 Jul 2019, 10:35 PM
Hello Rodolfo,

That error is happening because code is trying to update UI thread from another thread. Usually this error occurs when trying to update something bound to the UI thread form a background thread. However, in your case, I suspect the code is in the other Window's UI thread.

Specifically, the exception speaks to the error happening when our composition code, which relies on access to the Window's Compositor, is updating the Line series's color.


Dispatcher Test

When using multi-view application, you can access that Window's Dispatcher to access the UI thread. Try this for a test:

private async Task AddChartToAlternateViewAsync()
{
    // Get the first window that is not the Main instance
    var view = CoreApplication.Views.FirstOrDefault(v => v.IsMain == false);
 
    if(view == null)
        return;
 
    await view.Dispatcher.RunAsync((CoreDispatcherPriority.Normal), () =>
    {
        // Add chart here
    });
}

If that still presents the same exception, then it's likely that we have internal code that is referencing the CoreWindow dispatcher instead of current Dispatcher. In this case, I need to escalate the issue to the dev team to update that code to support multi instance apps.


Escalation

In order for me to escalate this to the development team, please share a small reproducible project by teaking the following steps:

1. Go to this link and click "Report a bug".
2. Then follow the steps to submit the ticket and attach the project (you can point back to this thread if you want)

When I see the case come in, I will test the project and escalate to the dev team. Thank you for your patience and understanding while we investigate further.

Regards,
Lance | Technical Support Engineer, Principal
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Rodolfo
Top achievements
Rank 1
answered on 24 Jul 2019, 11:09 PM

I think is an internal error of the library.

I tried with regular uwp ui controls and my usercontrols. There is no errors. Only with the telerik chart control.

I had a similar error with custom class: CoreWindow dispatcher instead of current Dispatcher.

Probably is the same with telerik chart.

I will report the bug.

the alternative "private async Task AddChartToAlternateViewAsync()
{..."

Looks a little like a hack. I will test it. But i guess the library should work without this code.

I am using the the open source version.

 

thanks,

rodolfo munoz

 

 

 

 

 

 

 

0
Lance | Manager Technical Support
Telerik team
answered on 25 Jul 2019, 06:46 PM
Hello Rodolfo,

I've spoken to the development team. There's actually already a GitHub thread open and it explains the reason for the problem (summary: SolidColorBrush holds Dispatcher): UI for UWP - Issue #288.

Option 1

In that GitHub thread,  Atanas explains the problem and presents an approach that changes the way the color is fetched.


Option 2

Another option you can take is to set the Chart's ContainerVisualsFactory to prevent the problem.

1. Create a class that inherits from ContainerVisualsFactory and return false from CanDrawContainerVisual

public class MyContainerVisualFactory : ContainerVisualsFactory
{
    protected override bool CanDrawContainerVisual(PresenterBase visualElement)
    {
        return false;
    }
}

2. Use an instance of that class for the Chart's ContainerVisualsFactory

<telerikChart:RadCartesianChart.ContainerVisualsFactory>
   <yourNamespace:MyContainerVisualFactory/>
</telerikChart:RadCartesianChart.ContainerVisualsFactory>


I hope that solves the issue. Let me know if you have any further trouble.

Regards,
Lance | Technical Support Engineer, Principal
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Rodolfo
Top achievements
Rank 1
answered on 25 Jul 2019, 08:56 PM

Hi,

 

I just read the the first option at GitHub. I think is too much trouble.

Will try the second one. I believe it is bug and must be fix inside the control source code. I already reported the bug.

After i test i will get back to you.

Thanks for your help.

 

 

 

 

0
Lance | Manager Technical Support
Telerik team
answered on 26 Jul 2019, 02:49 PM
Hello Rodolfo,

The first option is meant for the control's source code. Where you could fork the repo and update that code. In the end, that particular fix was already merged and released in R3 2018.

However, I have been able to replicate the exception using the latest version. I'm not sure if this is a regression or that solution doesn't work for this specific use case. Thus, I need to update my last statement to say that Option 2 is the only viable workaround I can provide at this time.

I have attached a demo app that reproduces the issue and shows that Option 2 is a valid workaround. Click the button in the app to open new views, each with a BarSeries.




The developers are now aware of this. I've added internal notes to the bug report with steps to reproduce so that they can investigate further. Finally, I have updated your Telerik Points as a small token of appreciation for bringing this to our attention.

If you have any further feedback or updates, please post them in the Bug Report so that the developers have the latest information.

Regards,
Lance | Technical Support Engineer, Principal
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Rodolfo
Top achievements
Rank 1
answered on 28 Jul 2019, 12:23 AM

I will try the second option. I will tell you my result asap.

 

 

0
Rodolfo
Top achievements
Rank 1
answered on 09 Aug 2019, 09:19 PM

I am about to test today. Too much work. Will replay asap. I just downloaded you zip attachment.

I just have to add that i am using Spline, Bar and Candlestick series. I assume is the same logic different output.

0
Lance | Manager Technical Support
Telerik team
answered on 09 Aug 2019, 09:36 PM

Hi Rodolfo,

Correct, the logic for creating the chart series is the same because they're all Cartesian series. It's the root control RadCartesianChart object that you're assigning the 

To you comment about too much work, this workaround is the simplest solution and is only a couple lines of code:

1. Add this class to your app somewhere:

public class MyContainerVisualFactory : ContainerVisualsFactory
{
	protected override bool CanDrawContainerVisual(PresenterBase visualElement)
	{
		return false;
	}
}

2. Use it on any chart that is going to be in a multi-instance view.

<chart:RadCartesianChart>
    <chart:RadCartesianChart.ContainerVisualsFactory>
        <local:MyContainerVisualFactory />
    </chart:RadCartesianChart.ContainerVisualsFactory>

    <!-- Your Series here -->
</chart:RadCartesianChart>

If you have any further trouble, update my demo so that it replicates the new problem and I'll forward it to the development team.

Regards, Lance | Technical Support Engineer, Principal
Progress Telerik

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Rodolfo
Top achievements
Rank 1
answered on 14 Aug 2019, 10:22 PM

Hi Lance,

It is working now. I notice that the char runs a little bit slower.

What is the visual spray ? Does it affect performance ?

I tried withe candlestick charts. As soon as finish spline and bars i will report.

Thanks you very much for your help. The companion code was very helpful.

Regards,

Rodolfo Munoz

 

 

 

 

 

 

 

0
Lance | Manager Technical Support
Telerik team
answered on 14 Aug 2019, 10:33 PM
Hello Rodolfo,

The slower performance is expected due to the fact that we're now using UI elements in the XAML layer instead of the Composition APIs to draw the visuals in the Composition layer. This is an unfortunate side effect of disable Composition visuals. Until there is a source code fix/solution implemented, this is the only way forward for now.

One way you can boost performance is to decrease the number visuals needed. Previously, when using Composition layer that sits under the XAML layer, you wouldn't have noticed the sheer number of elements being drawn to the UI because it is more powerful than XAML. Now that the chart is using the XAML layer, there are actual XAML elements being used to draw the chart elements (e.g. Ellipse, etc).

To decrease the number of elements needed, you can sample the data before assigning it to the ItemsSource of the series. In most cases, the user cannot tell the difference between 20,000 data points and 2,000 data points.

For example:

List<Data> smallerList = new List<Data>();
 
// Sample 2000 items to get to 200 items that can render much faster in a chart
for(var i = 0; i < HugeList.Count; i++)
{
    // Modulus 10 to sample every 10th item
    if(i % 10)
    {
        smallerList.Add(HugeList[i]);
    }
}
 
MySeries.ItemsSource = smallerList;

I hope this is helpful.

Regards,
Lance | Technical Support Engineer, Principal
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Rodolfo
Top achievements
Rank 1
answered on 14 Aug 2019, 10:57 PM

Lance,

Fortunately the max data points i am using is 800 and the less is 60.

The thing is that i am updating in real-time. I am testing right now. Of course, maximum speed and performance is always welcome.

Thanks for your tips !

 

 

Tags
Chart
Asked by
Rodolfo
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Rodolfo
Top achievements
Rank 1
Share this question
or