WPF window 不停止 timer/closing 并降低 RAM 使用率
WPF window not stopping timer/closing and lowering RAM usage
嘿,我已经尝试了很多方法来纠正我的 WPF 程序问题。 WPF 是一项伟大的技术,可用于制作非常好的应用程序,但它与 WinForm 不同的古怪命令有时让我感到不安。
我已加载主要 window 以及打开 MoviePosters 的事件 window:
namespace WpfApplication49
{
public partial class firstWindow : Window
{
public static bool exitLoading = false;
public static bool loadedMovies = false;
public static MoviePosters MP;
....[more code within this area]
private void myControl1_Click(object sender, myClickEventArgs e)
{
if (e.my.Tag.ToString().Contains("movieIcon"))
{
if (!loadedMovies)
{
MP = new MoviePosters();
MP.Show();
}
else
{
MP.Show();
}
}
....[more code within this area]
this.Topmost = false;
}
....[more code within this area]
}
我目前正在通过这种方式从我的 MoviePosters.xaml [=87= 加载一个 watchMovie.xaml ]:
namespace WpfApplication49
{
public partial class MoviePosters : Window
{
static watchingMovie MW;
....[more code within this area]
private void myControl1_Click(object sender, myClickEventArgs e)
{
MW = new watchingMovie((string)e.my.Tag.ToString())
MW.Show();
}
....[more code within this area]
}
}
上面的加载 window 就好了。然而,问题是当我关闭这个 window 和 return 回到原来的 window 时,它仍然在内存中并且计时器仍然有效!
watchingMovie.xaml的关闭代码:
namespace WpfApplication49
{
public partial class watchingMovie : Window
{
public readonly DispatcherTimer timer = new DispatcherTimer();
public watchingMovie(String movie)
{
InitializeComponent();
passedMovie = movie;
timer.Interval = TimeSpan.FromMilliseconds(200);
timer.Tick += new EventHandler(timer_Tick);
this.Topmost = true;
}
....[more code within this area]
public void Exit_Click(object sender, RoutedEventArgs e)
{
ME.Stop();
ME.Close();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
timer.Stop();
this.Close();
}
void timer_Tick(object sender, EventArgs e)
{
TimeSpan _duration = ME.NaturalDuration.TimeSpan;
TimeSpan remaining = _duration.Subtract(ME.Position);
if (!isDragging)
{
seekBar.Value = ME.Position.TotalSeconds;
currentposition = seekBar.Value;
lblMovieTime.Content = remaining.ToString(@"hh\:mm\:ss");
}
var totalTime = string.Format("{0:00}:{1:00}", (_duration.Hours * 60) + _duration.Minutes, _duration.Seconds);
var currentTime = string.Format("{0:00}:{1:00}", (remaining.Hours * 60) + remaining.Minutes, remaining.Seconds);
TimeSpan diff = remaining - _duration;
}
....[more code within this area]
}
}
从 firstWindow.xaml 开始,RAM 开始时为 ~59.0 MB。当它到达 MoviePoster window 时,使用的 RAM 是 ~105.4 MB。当我加载 watchingMovie window 时,它会上升到 ~145.0 MB。当我退出 watchingMovie window(使用 this.Close())时,它会带我回到 MoviePoster window 然后 RAM 是 ~143.0 MB。每次我加载 watchingMovie window 时,RAM 使用率就会上升!
所以...
- ram 不应该像以前那样回到 ~105 MB 左右吗
在 加载 watchingMovie window 因为我关闭了 window?
- 我不明白为什么计时器还在计时
电影 - 你知道的,因为一旦
window本身已经关闭了?
这是一个简短的动画 GIF,展示了从我的程序开始到 watchingMovie window.
退出的过程
更新 #1
在这种情况下调用 GC 是完全没有意义的。
由于计时器继续为你工作,这意味着一些对对象的引用仍然存在,只要这些引用存在,GC 就不会收集这些对象。
在Window关闭事件中,需要停止定时器并清除所有静态链接。
像这样:
public watchingMovie(String movie)
{
InitializeComponent();
Closed += OnWindowClosed;
passedMovie = movie;
timer.Interval = TimeSpan.FromMilliseconds(200);
timer.Tick += timer_Tick;
this.Topmost = true;
}
void timer_Tick(object sender, EventArgs e)
{
// Some Code
}
private void OnWindowClosed(object sender, EventArgs e)
{
timer.Stop();
timer.Tick -= timer_Tick;
ME.Stop();
ME.Close();
ME = null;
}
private void myControl1_Click(object sender, myClickEventArgs e)
{
MW = new watchingMovie((string)e.my.Tag.ToString());
MW.Closed += (_, __) => MW = null;
MW.Show();
}
public firstWindow()
{
InitializeComponent();
Closed += (_, __) => MP?.Close();
}
private void myControl1_Click(object sender, myClickEventArgs e)
{
if (e.my.Tag.ToString().Contains("movieIcon"))
{
if (!loadedMovies)
{
MP = new MoviePosters();
MP.Closed += (_, __) => MP = null;
MP.Show();
}
else
{
MP.Show();
}
}
}
P.S.我强烈建议你完全放弃存储动态创建对象的静态成员(字段和属性)。
静态成员只能用于存储对应用程序会话期间必须存在的对象的引用。
在会话结束之前,不应关闭、销毁此类对象。
嘿,我已经尝试了很多方法来纠正我的 WPF 程序问题。 WPF 是一项伟大的技术,可用于制作非常好的应用程序,但它与 WinForm 不同的古怪命令有时让我感到不安。
我已加载主要 window 以及打开 MoviePosters 的事件 window:
namespace WpfApplication49
{
public partial class firstWindow : Window
{
public static bool exitLoading = false;
public static bool loadedMovies = false;
public static MoviePosters MP;
....[more code within this area]
private void myControl1_Click(object sender, myClickEventArgs e)
{
if (e.my.Tag.ToString().Contains("movieIcon"))
{
if (!loadedMovies)
{
MP = new MoviePosters();
MP.Show();
}
else
{
MP.Show();
}
}
....[more code within this area]
this.Topmost = false;
}
....[more code within this area]
}
我目前正在通过这种方式从我的 MoviePosters.xaml [=87= 加载一个 watchMovie.xaml ]:
namespace WpfApplication49
{
public partial class MoviePosters : Window
{
static watchingMovie MW;
....[more code within this area]
private void myControl1_Click(object sender, myClickEventArgs e)
{
MW = new watchingMovie((string)e.my.Tag.ToString())
MW.Show();
}
....[more code within this area]
}
}
上面的加载 window 就好了。然而,问题是当我关闭这个 window 和 return 回到原来的 window 时,它仍然在内存中并且计时器仍然有效!
watchingMovie.xaml的关闭代码:
namespace WpfApplication49
{
public partial class watchingMovie : Window
{
public readonly DispatcherTimer timer = new DispatcherTimer();
public watchingMovie(String movie)
{
InitializeComponent();
passedMovie = movie;
timer.Interval = TimeSpan.FromMilliseconds(200);
timer.Tick += new EventHandler(timer_Tick);
this.Topmost = true;
}
....[more code within this area]
public void Exit_Click(object sender, RoutedEventArgs e)
{
ME.Stop();
ME.Close();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
timer.Stop();
this.Close();
}
void timer_Tick(object sender, EventArgs e)
{
TimeSpan _duration = ME.NaturalDuration.TimeSpan;
TimeSpan remaining = _duration.Subtract(ME.Position);
if (!isDragging)
{
seekBar.Value = ME.Position.TotalSeconds;
currentposition = seekBar.Value;
lblMovieTime.Content = remaining.ToString(@"hh\:mm\:ss");
}
var totalTime = string.Format("{0:00}:{1:00}", (_duration.Hours * 60) + _duration.Minutes, _duration.Seconds);
var currentTime = string.Format("{0:00}:{1:00}", (remaining.Hours * 60) + remaining.Minutes, remaining.Seconds);
TimeSpan diff = remaining - _duration;
}
....[more code within this area]
}
}
从 firstWindow.xaml 开始,RAM 开始时为 ~59.0 MB。当它到达 MoviePoster window 时,使用的 RAM 是 ~105.4 MB。当我加载 watchingMovie window 时,它会上升到 ~145.0 MB。当我退出 watchingMovie window(使用 this.Close())时,它会带我回到 MoviePoster window 然后 RAM 是 ~143.0 MB。每次我加载 watchingMovie window 时,RAM 使用率就会上升!
所以...
- ram 不应该像以前那样回到 ~105 MB 左右吗 在 加载 watchingMovie window 因为我关闭了 window?
- 我不明白为什么计时器还在计时 电影 - 你知道的,因为一旦 window本身已经关闭了?
这是一个简短的动画 GIF,展示了从我的程序开始到 watchingMovie window.
退出的过程更新 #1
在这种情况下调用 GC 是完全没有意义的。
由于计时器继续为你工作,这意味着一些对对象的引用仍然存在,只要这些引用存在,GC 就不会收集这些对象。
在Window关闭事件中,需要停止定时器并清除所有静态链接。
像这样:
public watchingMovie(String movie)
{
InitializeComponent();
Closed += OnWindowClosed;
passedMovie = movie;
timer.Interval = TimeSpan.FromMilliseconds(200);
timer.Tick += timer_Tick;
this.Topmost = true;
}
void timer_Tick(object sender, EventArgs e)
{
// Some Code
}
private void OnWindowClosed(object sender, EventArgs e)
{
timer.Stop();
timer.Tick -= timer_Tick;
ME.Stop();
ME.Close();
ME = null;
}
private void myControl1_Click(object sender, myClickEventArgs e)
{
MW = new watchingMovie((string)e.my.Tag.ToString());
MW.Closed += (_, __) => MW = null;
MW.Show();
}
public firstWindow()
{
InitializeComponent();
Closed += (_, __) => MP?.Close();
}
private void myControl1_Click(object sender, myClickEventArgs e)
{
if (e.my.Tag.ToString().Contains("movieIcon"))
{
if (!loadedMovies)
{
MP = new MoviePosters();
MP.Closed += (_, __) => MP = null;
MP.Show();
}
else
{
MP.Show();
}
}
}
P.S.我强烈建议你完全放弃存储动态创建对象的静态成员(字段和属性)。
静态成员只能用于存储对应用程序会话期间必须存在的对象的引用。
在会话结束之前,不应关闭、销毁此类对象。