2015-11-01 50 views
0

我做了一个使用c#的幻灯片,代码运行良好,并没有给我任何错误,但是当我在30-60秒后点击播放按钮时,它停止并让我走出内存异常System.Drawing.dll。任何想法来解决这个问题?谢谢C#内存不足在System.Drawing.dll中的异常

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Drawing; 
using System.IO; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
namespace Slide_Show 
{ 
    public partial class SlideShow : Form 
{ 
    public SlideShow() 
    { 
     InitializeComponent(); 
     if (timer.Interval < 200) 
     { 
      timer.Interval = 100; 
     } 
     else if(timer.Interval > 8000) 
     { 
      timer.Interval = 600; 
     } 
     else{ 
      timer.Interval = 2000; 
     } 
    } 
    string dir; 
    private void btnImagesSelection_Click(object sender, EventArgs e) 
     { 
     FolderBrowserDialog asked = new FolderBrowserDialog(); 
     if (asked.ShowDialog() == DialogResult.OK) 
     { 
      string folName = asked.SelectedPath; 
      foreach (string fullfol in Directory.GetFiles(folName)) 
      { 
       dir = fullfol.Substring(0, fullfol.LastIndexOf(("\\"))); 
       picImages.Image = Image.FromFile(fullfol); 
       lstImages.Items.Add(Path.GetFileName(fullfol)); 
       lblNum.Text = lstImages.Items.Count.ToString() + "/" + lstImages.Items.Count.ToString(); 
      } 
     } 

    } 

    private void lstImages_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     string curitem = lstImages.SelectedItem.ToString(); 
     picImages.Image = Image.FromFile(dir+"\\"+curitem); 
     lblNum.Text = (lstImages.SelectedIndex+1).ToString() + "/" + lstImages.Items.Count.ToString(); 
    } 
    bool flip = true; 
    int i = 0; 
    private void btnPlay_Click(object sender, EventArgs e) 
    { 
     timer.Start(); 
     timer.Interval = 1000; 
     timer.Tick += new EventHandler(timetick); 
    } 
    void timetick(object sender, EventArgs e) 
    { 

     int numitems = lstImages.Items.Count; 
     if (flip) 
      if (i < numitems) 
      { 
       try 
       { 
        lblNum.Text = (i + 1) + "/" + numitems; 
        picImages.Image = Image.FromFile(dir + "\\" + lstImages.Items[i].ToString()); 
        i += 1; 
       } 
       catch 
       { 
        timer.Stop(); 
       } 
      } 
      else if (i == numitems) 
      { 
       i = 0; 
      } 
     flip = !flip; 
    } 

    private void btnSlow_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      timer.Interval *= 2; 
     } 
     catch 
     { 
      timer.Interval = 6000; 
     } 
    } 

    private void btnFast_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      timer.Interval /= 2; 
     } 
     catch 
     { 
      timer.Interval = 100; 
     } 

    } 

    private void btnStop_Click(object sender, EventArgs e) 
    { 
     timer.Stop(); 
    } 

} 

}

+1

你的arent的任何图像处置加载 – Plutonix

+0

分配,如果一个新的插入'之前(picImages.Image!= NULL)picImages.Image.Dispose();' – TaW

+0

@TaW你不应该处理的分配新图像之前的图像。它可能会导致错误 –

回答

2

Image类保存图像数据作为非托管资源。这些资源不能通过Garbage Collector卸载,并且当您拨打Dispose方法或finalization时,内存将被释放。 Finalization对于处理大量图像来说太慢,所以每次加载新图像时都应该丢弃旧图像。

private void LoadNewImage(string path) 
{ 
    var oldImage = picImages.Image; 
    picImages.Image = Image.FromFile(dir+"\\"+curitem); 
    if(oldImage!= null) 
    { 
     oldImage.Dispose(); 
    } 
} 
+0

你是对的,现在我明白它是如何工作的,谢谢你:) – AHA27

+0

你也可以尝试在调用oldImage.Dispose()之后使用GC.Collect()和GC.WaitForPendingFinalizers()。尽管它们是相当昂贵的操作,但即使我调用Image.Dispose()方法,我也有时会使用OutOfMemoryExceptions。 – eMko