You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 如何释放以编程方式创建的ColorAnimation和Storyboard对象

实现逻辑说明

.NET 中 Storyboard、ColorAnimation 都属于托管对象,本身不提供手动释放的接口,完全由 GC(垃圾回收器)负责回收,只要切断所有根引用,GC 会在合适的时机自动回收对应的内存。

现有释放逻辑的优化

你原来的代码中仅调用 Stop() 还不够,需要额外切断所有引用链,才能确保对象可以被GC回收,注释处的代码可以补充为:

GridItemAnimationStoryBoard.Stop();
// 清除动画的目标绑定,切断动画对UI元素的引用
Storyboard.SetTarget(GridItemColorAnimation, null);
// 从情节提要中移除动画
GridItemAnimationStoryBoard.Children.Clear();
// 全局变量置空,切断根引用
GridItemColorAnimation = null;
GridItemAnimationStoryBoard = null;

额外优化建议

  1. 监听动画完成事件自动清理
    可以给Storyboard绑定Completed事件,动画执行结束后自动执行清理逻辑,不需要等到下次点击才清理上一次的对象:
GridItemAnimationStoryBoard.Completed += (s, e) =>
{
    var sb = s as Storyboard;
    sb.Stop();
    foreach (var anim in sb.Children)
    {
        Storyboard.SetTarget(anim, null);
    }
    sb.Children.Clear();
    // 如果你用列表存了所有Storyboard,在这里移除对应实例即可
};
  1. 复用动画对象(更推荐)
    不需要每次点击都新建动画和Storyboard实例,只要重置目标、属性值就可以复用,减少GC压力:
// 全局只初始化一次
if (GridItemAnimationStoryBoard == null)
{
    GridItemColorAnimation = new ColorAnimation();
    GridItemAnimationStoryBoard = new Storyboard();
    GridItemColorAnimation.EnableDependentAnimation = true;
    GridItemAnimationStoryBoard.Children.Add(GridItemColorAnimation);
    Storyboard.SetTargetProperty(GridItemColorAnimation, "Color");
}
// 每次点击只修改动态属性
GridItemAnimationStoryBoard.Stop();
var duration = new Duration(TimeSpan.FromMilliseconds(employees_data_model.selected_employee_contact.DeleteEmployee == true ? 300 : 1000));
GridItemColorAnimation.Duration = duration;
GridItemAnimationStoryBoard.Duration = duration;
Storyboard.SetTarget(GridItemColorAnimation, GridItem.Background);
GridItemColorAnimation.To = employees_data_model.selected_employee_contact.DeleteEmployee == true ? ColorHelper.FromArgb(150, 255, 100, 100) : ColorHelper.FromArgb(0, 0, 0, 0);
GridItemAnimationStoryBoard.Begin();
  1. 注意ListView虚拟化适配
    如果你的ListView开启了虚拟化,条目滑出可视区域时会被系统回收,此时如果动画还在执行,要提前停止并清理对应动画的目标绑定,避免出现内存泄漏。

现有方案的合理性

你当前采用的Stop()+清空存储列表的方案已经符合GC回收要求,只要没有其他静态变量、全局事件持有这些Storyboard的引用,就不会出现内存泄漏。非特殊情况不建议手动调用GC.Collect(),频繁触发垃圾回收反而会降低应用运行性能。


内容的提问来源于stack exchange,提问作者Eugen M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:15:03