新线程内存使用量不会停止增加
Posted
技术标签:
【中文标题】新线程内存使用量不会停止增加【英文标题】:New thread memory usage won't stop increase 【发布时间】:2021-05-02 02:46:51 【问题描述】:我最近发现了如何在后台执行任务,并尝试在 WPF 中使用这些进行测试。
我尝试测试的是在图片框中创建图片轮播。
为此,我阅读了this、this 和this,这就是我所拥有的:
public partial class Page2 : Page
public Thread backgroundcaroussel;
public Page2()
InitializeComponent();
backgroundcaroussel = new Thread(ImgFlip);
backgroundcaroussel.IsBackground = true;
backgroundcaroussel.Start();
private void Button_Click(object sender, RoutedEventArgs e)
backgroundcaroussel.Abort();
MainWindow.Fenetre.Content = MainWindow.pgUn;
private void ImgFlip()
Again:
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
BitmapSource btmSrc1 = Imaging.CreateBitmapSourceFromHBitmap(Properties.Resources._1080p_1.GetHbitmap(),
IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
img_moins.Source = btmSrc1;
);
Thread.Sleep(2000);
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,(ThreadStart)delegate ()
BitmapSource btmSrc2 = Imaging.CreateBitmapSourceFromHBitmap(Properties.Resources._1080p_2.GetHbitmap(),
IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
img_moins.Source = btmSrc2;
);
Thread.Sleep(2000);
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
BitmapSource btmSrc3 = Imaging.CreateBitmapSourceFromHBitmap(Properties.Resources._1080p_3.GetHbitmap(),
IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
img_moins.Source = btmSrc3;
);
Thread.Sleep(2000);
goto Again;
当我使用此代码时,内存使用量不会停止增加并达到 1 或 2 Go(在我停止之前)。 我不认为这是正常的:)
我还阅读了this、this 和this 来解决问题,但不清楚该怎么做。
如何解决这种内存消耗? 我是否使用了正确的方法?
【问题讨论】:
在一个大部分时间都在休眠的线程中执行此操作是可怕的。请改用计时器,最好是 DispatcherTimer。但是感谢您向我们展示goto
仍然存在。您应该阅读一本介绍性 C# 的书,然后可能是一本关于 WPF 的书。
请注意,尽管在 UI 线程中调用了 DispatcherTimer 的 Tick 事件,但您仍然可以声明 Tick 处理程序方法 async
并运行创建 BitmapSource 的后台任务。
您经常调用Bitmap.GetHbitmap 方法。如果你看一下文档,你可以找到一个小注释:“YOU是负责调用GDI DeleteObject方法来释放GDI位图对象使用的内存”
另外说明,您通常不会从Properties.Resources
中的System.Drawing.Bitmap
资源加载位图。相反,将图像文件添加到 Visual Studio 项目,将其构建操作设置为资源并从程序集资源包 URI 加载 BitmapImages。参见例如这里:***.com/a/22957974/1136211
请不要使用goto,除非你绝对必须。在你的情况下,你不必。它和while(true)
一样,只是更臭。
【参考方案1】:
代码中内存消耗增加的问题是您必须通过调用DeleteObject
来删除GetHbitmap
返回的句柄,例如如此处所述:https://***.com/a/5827468/1136211
除此之外,在 WPF 应用程序中,您会以完全不同的方式实现整个逻辑。
您不会在Properties/Resources.resx
中使用位图资源,而是只需将图像文件添加到您的 Visual Studio 项目中,例如在名为“Images”的项目文件夹中。然后将这些文件Resource
的构建操作设置为例如此处显示:https://***.com/a/12693661/1136211
在启动时,将所有这些图像资源加载到一个列表中。然后启动一个 DispatcherTimer,将它们循环分配给 Image 元素的 Source 属性。
public partial class MainWindow : Window
private readonly List<ImageSource> images = new List<ImageSource>();
private int imageIndex;
public MainWindow()
InitializeComponent();
images.Add(new BitmapImage(new Uri("pack://application:,,,/Images/Image1.png")));
images.Add(new BitmapImage(new Uri("pack://application:,,,/Images/Image2.png")));
images.Add(new BitmapImage(new Uri("pack://application:,,,/Images/Image3.png")));
ShowNextImage();
var timer = new DispatcherTimer Interval = TimeSpan.FromSeconds(2) ;
timer.Tick += TimerTick;
timer.Start();
private void TimerTick(object sender, EventArgs e)
ShowNextImage();
private void ShowNextImage()
image.Source = images[imageIndex];
imageIndex = (imageIndex + 1) % images.Count;
【讨论】:
非常感谢!让我知道在哪里可以了解更多相关信息。我保证你会阅读有关 wpf 的书籍 :) Adan Nathan 的 IMO “WPF Unleashed”是一本很棒的书。以上是关于新线程内存使用量不会停止增加的主要内容,如果未能解决你的问题,请参考以下文章