Элементы управления Silverlight с использованием xaml — потребление ресурсов

#c# #xaml #silverlight #resources #silverlight-5.0

#c# #xaml #silverlight #Ресурсы #silverlight-5.0

Вопрос:

Я столкнулся с проблемой потребления памяти в приложении Silverlight 5.

После нескольких дней измерений я увидел, что основными потребителями памяти являются пользовательские пользовательские элементы управления (с xaml), и что эти элементы управления выделяются на фоне остальных элементов управления, которые не имеют xaml (например, унаследованные от System.Windows.Элементы управления.Текстовое поле (System.Windows.Элементы управления.Контроль)).

Я был удивлен, узнав, что при вызовах элемента управления Silverlight InitializeComponent(); (constructor) Фреймворк вызывается System.Windows.Application.LoadComponent(Object, Uri) каждый раз, чтобы получить xaml.

Итак, если вы создаете 500 элементов управления динамически (одного и того же типа), Framework будет вызывать LoadComponent() 500 раз? Я ожидал, что xaml будет загружен только при первом создании экземпляра элемента управления, и не более LoadComponent() после этого.

Мои вопросы:

  • Можно ли включить какой-то механизм кэширования» в Silverlight, чтобы при создании экземпляра некоторого UserControl Фреймворк распознал, что xaml был загружен ранее, и чтобы не делать то же самое снова, загружает xaml только в первый раз?
  • Существует ли какой-либо другой механизм или хорошая практика, позволяющие избежать загрузки одного и того же xaml каждый раз?

У меня есть базовый пример с упомянутыми типами элементов управления. Вы можете найти пример кода ниже. Это всего лишь базовый пример, без каких-либо привязок, объектов DataContext, свойств зависимостей и так далее.

Элементы управления

MyTextBox.cs, который наследуется от System.Windows.Элементы управления.Текстовое поле

    using System.Windows.Controls;

    namespace TestControls.Controls
    {
        public class МyTextBox : TextBox
        {

            public МyTextBox()
            {
                Text = "MyTextBox";
            }
        }
    }
  

myText.xaml

 <UserControl x:Class="TestControls.Controls.MyText"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock Name="Text"/>
    </Grid>
</UserControl>
  

myText.xaml.cs

 using System.Windows.Controls;

namespace TestControls.Controls
{
    public partial class MyText : UserControl
    {
        public MyText()
        {
            InitializeComponent();
            Text.Text = "MyTextControl";
        }
    }
}
  

Приложение

MainPage.xaml

  <UserControl x:Class="TestControlsApplication.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Name="Panel"/>
    </Grid>
</UserControl>
  

MainPage.xaml.cs

 using System.Windows.Controls;
using TestControls.Controls;

namespace TestControlsApplication
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            for (int i = 0; i < 1000; i  )
            {
                MyText t = new MyText();
                МyTextBox tb = new МyTextBox();
                Panel.Children.Add(t);
                Panel.Children.Add(tb);
            }
        }
    }
}
  

Элемент управления myText (с xaml) выделяет 5,1 МБ (все экземпляры) и MyTextBox, который наследует System.Windows.Элементы управления.Текстовое поле выделило 0,4 МБ.

Выделение памяти (трассировка точек Jetbrains)

Аналогичная ситуация возникает, когда мы сравниваем время создания двух элементов управления.

Трассировка - количество вызовов и время выполнения

Комментарии:

1. Если вы создаете элемент управления полностью в коде, ему не нужно ничего загружать. В противном случае он должен создать все элементы управления, указанные в xaml, задать их свойства и т. Д. вот почему он читает его каждый раз. Думайте о xaml как о списке задач для элемента управления. Для создания экземпляра вам нужен такой список: либо в виде кода, либо в виде xaml, верно?

2. Другой момент заключается в том, что вы создаете один и тот же элемент управления 1000 раз. Обычно у вас их не так много. Используйте элементы управления списком ( ListBox , ListView , и т.д.) они поддерживают виртуализацию и будут создавать элементы управления только для видимых в данный момент элементов, экономя вам много памяти и времени.

3. @Sinatr: Первый вопрос: Да, это вариант — реализовать управление без xaml — полностью в коде, как вы сказали. Но я пытаюсь избежать этого (у меня более одного элемента управления с такого рода проблемами) и посмотреть, есть ли волшебная кнопка включения / выключения в SL (или WPF) для выполнения ,,кэширования» xaml. Я не нашел ответа во время своего расследования, вот почему я спрашиваю. 🙂

4. @Sinatr : Второй момент: виртуализация реализована в местах, где доступна такая презентация. В некоторых частях приложения (бизнес-приложения) пользователю должен быть представлен большой объем данных, поэтому все эти элементы управления создаются в какой-то момент. Если у меня есть большое количество элементов управления (с xaml), которые потребляют в 12-13 раз больше ресурсов, чем аналогичные элементы управления (только без xaml), виртуализация — это лишь верхушка айсберга.