Информация об окружающей среде:
Windows 7 64bit SP1
6 ГБ памяти
Процессор Intel® Core ™ TM i5-2400S @ 2,50 ГГц (4 ядра)
Silverlight 5
У меня очень ужасные проблемы с производительностью DropShadowEffect
в Silerlight.
Я создал для него свернутую демоверсию:
http://www.peterlee.com.cn/public/ShadowEffectTestDemo/ShadowEffectTestTestPage.html
Нажмите кнопку Zoom
, чтобы попытаться увеличить холст (в форме звезды со DropShadowEffect
). Вы обнаружите, что когда Zoom = 64
, ваш процессор и память очень сумасшедшие.
Но если вы удалите DropShadowEffect
, нажав кнопку Remove Effect
, а затем увеличите его, все будет в порядке.
Однако, если мы используем TextBlock
с DropShadowEffect
, все в порядке. Вы можете попробовать это, нажав кнопку «Использовать TextBlock`.
Я не знаю, что Silverlight имеет дело с TextBlock и моей индивидуальной формой звезды для DropShadowEffect
.
Пожалуйста, помогите мне. Спасибо.
UPDATE :
Согласно ответам:
Я также пробовал это в режиме выпуска (теперь демонстрационная ссылка примера была построена в режиме выпуска);
Я также добавил ускорение GPA, предложенное ChrisF:
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<param name="EnableGPUAcceleration" value="true" />
<param name="source" value="ShadowEffectTest.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="5.0.61118.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object>
Вот ОБНОВЛЕННЫЙ код
MainPage.xmal:
<UserControl x:Class="ShadowEffectTest.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">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="btnZoom" Width="75" Height="23" Content="Zoom"
Grid.Column="0" Grid.Row="0"
Click="btnZoom_Click"/>
<Button x:Name="btnRemoveEffect" Width="100" Height="23" Content="Remove Effect"
Grid.Row="0" Grid.Column="1"
Click="btnRemoveEffect_Click"/>
<Button x:Name="btnUseTextBlock" Width="120" Height="23" Content="Use TextBlock"
Grid.Row="1" Grid.Column="0"
Click="btnUseTextBlock_Click" />
<Canvas x:Name="mainCanvas" Width="200" Height="150" Background="LightBlue"
Grid.Column="1" Grid.Row="1" />
</Grid>
</UserControl>
MainPage.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Media.Effects;
namespace ShadowEffectTest
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
// These are the points for a Star shape
List<Point> points = new List<Point>()
{
new Point(0, 36.3634469292486),
new Point(-12.3606797688474, 43.2188191057189),
new Point(-24.7213595376948, 50.0741912821893),
new Point(-37.0820393065422, 56.9295634586596),
new Point(-34.4313595448175, 42.9654855127096),
new Point(-31.7806797830927, 29.0014075667595),
new Point(-29.130000021368, 15.0373296208095),
new Point(-39.4200000080385, 5.31010468057062),
new Point(-49.709999994709, -4.41712025966827),
new Point(-59.9999999813794, -14.1443451999072),
new Point(-46.0011100186002, -15.919247828416),
new Point(-32.002220055821, -17.694150456925),
new Point(-18.0033300930418, -19.4690530854338),
new Point(-12.0022200620278, -32.3361808961241),
new Point(-6.00111003101392, -45.2033087068145),
new Point(0, -58.0704365175048),
new Point(6.00111003101392, -45.2033087068145),
new Point(12.0022200620278, -32.3361808961241),
new Point(18.0033300930418, -19.4690530854338),
new Point(32.002220055821, -17.694150456925),
new Point(46.0011100186002, -15.919247828416),
new Point(59.9999999813794, -14.1443451999072),
new Point(49.709999994709, -4.41712025966827),
new Point(39.4200000080385, 5.31010468057062),
new Point(29.130000021368, 15.0373296208095),
new Point(31.7806797830927, 29.0014075667595),
new Point(34.4313595448175, 42.9654855127096),
new Point(37.0820393065422, 56.9295634586596),
new Point(24.7213595376948, 50.0741912821893),
new Point(12.3606797688474, 43.2188191057189),
new Point(0, 36.3634469292486)
};
uie = RenderBezier(points);
// This the evil for the performance issues (crazy memory and CPU)
uie.Effect = ShadowEffect;
uie.CacheMode = new BitmapCache();
uie.SetValue(Canvas.LeftProperty, 25.0);
uie.SetValue(Canvas.TopProperty, 25.0);
mainCanvas.Children.Add(uie);
}
private UIElement uie = null;
public Path RenderBezier(List<Point> ctrlPoints, List<List<Point>> innersCtrlPoints = null)
{
// Step 0: Merge ctrlPoints lists
List<List<Point>> ctrlPointsLists;
if (innersCtrlPoints == null)
{
ctrlPointsLists = new List<List<Point>>(1);
ctrlPointsLists.Add(ctrlPoints);
}
else
{
ctrlPointsLists = new List<List<Point>>(1 + innersCtrlPoints.Count);
ctrlPointsLists.Add(ctrlPoints);
foreach (List<Point> list in innersCtrlPoints)
ctrlPointsLists.Add(list);
}
PathGeometry pg = new PathGeometry();
foreach (List<Point> list in ctrlPointsLists)
{
// Step 0: check (Debug.Assert)
Debug.Assert(list.Count % 3 == 1,
"public Path RenderBezier(IList<Point> ctrlPoints): number of control points is not 3n+1.");
int n = (list.Count - 1) / 3; // Number of BezierSegments
Debug.Assert(n > 0,
"public Path RenderBezier(IList<Point> ctrlPoints): at least one Bezier segment required.");
// Step 1: Add BezierSegments to PathFigure
PathFigure pf = new PathFigure();
pf.StartPoint = list[0];
for (int i = 0; i < n; ++i)
pf.Segments.Add(GetBezierSegment(
list[3 * i + 1],
list[3 * i + 2],
list[3 * i + 3]
));
// Step 2: Add PathFigures to PathGeometry
pg.Figures.Add(pf);
}
// Step 3: Add PathGemotry to GeometryGroup
GeometryGroup gg = new GeometryGroup();
gg.Children.Add(pg);
// Step 4: Set GeometryGroup as Path.Data
Path path = new Path();
path.Data = gg;
// Step 5: Set some Path properties
// if (ShowOutline)
{
path.Stroke = new SolidColorBrush(Colors.Black);
path.StrokeThickness = 1.0;
path.StrokeEndLineCap = PenLineCap.Round;
path.StrokeLineJoin = PenLineJoin.Round;
path.StrokeStartLineCap = PenLineCap.Round;
}
// Finally, return it
return path;
}
// This the evil for the performance issues (crazy memory and CPU)
private static DropShadowEffect ShadowEffect
{
get
{
return new DropShadowEffect()
{
Color = Colors.Blue,
BlurRadius = 5,
Direction = 0,
ShadowDepth = 0
};
}
}
private static BezierSegment GetBezierSegment(Point p1, Point p2, Point p3)
{
BezierSegment bs = new BezierSegment();
bs.Point1 = p1;
bs.Point2 = p2;
bs.Point3 = p3;
return bs;
}
public static readonly double[] ZoomingSteps = new double[]
{
1.0,
1.5,
2.0,
3.0,
4.0,
6.0,
8.0,
12.0,
16.0,
24.0,
32.0,
48.0,
64.0,
128.0
};
private int index = 0;
private void btnZoom_Click(object sender, RoutedEventArgs e)
{
if (index >= ZoomingSteps.Length - 1)
return;
ScaleTransform st = new ScaleTransform();
st.ScaleX = st.ScaleY = ZoomingSteps[index++];
btnZoom.Content = ZoomingSteps[index].ToString();
mainCanvas.RenderTransform = st;
}
private void btnRemoveEffect_Click(object sender, RoutedEventArgs e)
{
index = 0;
btnZoom.Content = "Zoom";
uie.Effect = null;
mainCanvas.RenderTransform = new ScaleTransform();
}
// If I use TextBlock as the child UIElement, then everything is okay
// path = new TextBlock() { Text = "Text Block" };
private void btnUseTextBlock_Click(object sender, RoutedEventArgs e)
{
mainCanvas.Children.Remove(uie);
index = 0;
btnZoom.Content = "Zoom";
uie = new TextBlock() { Text = "Text Block" };
mainCanvas.Children.Add(uie);
uie.Effect = ShadowEffect;
uie.CacheMode = new BitmapCache();
mainCanvas.RenderTransform = new ScaleTransform();
}
}
}