WPF模糊效果导致高CPU即使崩溃

  • 本文关键字:CPU 崩溃 模糊 WPF wpf
  • 更新时间 :
  • 英文 :


我们必须在WPF应用程序中显示一个合法的弹出窗口。当弹出窗口显示时,我们对下面的视图使用模糊效果。

最近我们意识到这会导致高GPU使用率。因为后台的旋转控件。活动内容越多,GPU使用量越大。

当弹出窗口基于属性显示时,我们折叠这个旋转控件。但这无济于事。只有当我们在主窗口中将其设置为折叠时。

我们尝试了很多东西,例如BitmapCache和其他技术,但到目前为止还没有成功。

这里有一个例子:https://github.com/rmoergeli/BlurEffectTest.git

我调查了演示代码中的问题隐藏在你的动画中:它不会停止从visiblecollapsed的可见性。

所以我找到了一个解决方案,在MSDN资源的帮助下停止动画被折叠。

public partial class Spinner : UserControl
{
private Canvas _content;
private Storyboard _rotationStoryboard;
public Spinner()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
DefineContent();
SizeChanged += Spinner_SizeChanged;
IsVisibleChanged += Spinner_IsVisibleChanged;
Loaded += Spinner_Loaded;
}
private void Spinner_Loaded(object sender, RoutedEventArgs e)
{
_rotationStoryboard.Begin(this, isControllable: true);
}
private void Spinner_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is bool isVisible && isVisible)
_rotationStoryboard.Resume(this);
else
_rotationStoryboard.Pause(this);
}
private void DefineContent()
{
_content = new Canvas();
//set content render transform origin point to center
_content.RenderTransformOrigin = new Point(0.5 , 0.5);
_content.RenderTransform = new RotateTransform(angle: 0);
// Assign the canvas a name by
// registering it with the page, so that
// it can be targeted by storyboard
// animations.
RegisterName("animatableCanvas", _content);
Content = _content;
DefineAnimatableContent();
// Create an animation and a storyboard to animate the
// canvas.
DoubleAnimation doubleAnimation = new DoubleAnimation
{
To = 360,
Duration = new Duration(TimeSpan.FromSeconds(3)),
RepeatBehavior = RepeatBehavior.Forever
};
Storyboard.SetTargetName(doubleAnimation, "animatableCanvas");
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("RenderTransform.Angle"));
_rotationStoryboard = new Storyboard();
_rotationStoryboard.Children.Add(doubleAnimation);
}
private void DefineAnimatableContent() //renamed Refresh method
{
int n = Balls;
double size = BallSize;
_content.Children.Clear();
double x = ActualWidth / 2;
double y = ActualHeight / 2;
double r = Math.Min(x, y) - size / 2;
double doubleN = Convert.ToDouble(n);
for (int i = 1; i <= n; i++)
{
double doubleI = Convert.ToDouble(i);
double x1 = x + Math.Cos(doubleI / doubleN * 2d * Math.PI) * r - size / 2;
double y1 = y + Math.Sin(doubleI / doubleN * 2d * Math.PI) * r - size / 2;
var e = new Ellipse
{
Fill = BallBrush,
Opacity = doubleI / doubleN,
Height = size,
Width = size
};
Canvas.SetLeft(e, x1);
Canvas.SetTop(e, y1);
_content.Children.Add(e);
};
}
#region Event Handlers
private void Spinner_SizeChanged(object sender, SizeChangedEventArgs e)
{
//we dont need this anymore as we set content render transform origin point to content center
//Transform.CenterX = ActualWidth / 2;
//Transform.CenterY = ActualHeight / 2;
DefineAnimatableContent();
}
#endregion
//other logic
}

此代码在改变Spiner控件可见性时停止动画。但是你可以用任何你需要的触发器来暂停和恢复动画。

注意!使用这种方法,您可以在代码中定义所有内容(不仅仅是可动画的部分),因此您不再需要Spinner.xaml资源。

最新更新