Search code examples
c#winformspictureboxanimated-gif

System.Runtime.InteropServicesExternalException occured in System.Drawing.dll


I have a 28MB animated gif as an embedded resource which I am trying to load on my 'About' form.

The forms code is as follows :

About

private void About_Load(object sender, EventArgs e)
{
    pictureBox1.Image = EmbeddedResources.image("mygif.gif");
}

EmbeddedResources (simplified)

public class EmbeddedResources
{
    public static Assembly self { get { return Assembly.GetExecutingAssembly(); } }

    public static Image image(string name)
    {
        Image result = null;
        using (Stream res = self.GetManifestResourceStream("MyProject." + name))
        {
            result = Image.FromStream(res);
        }
        return result;
    }

}

The code seems to have no issues finding the resource, as result in EmbeddedResources.image() is filled with the data (not null), and the line pictureBox1.Image = EmbeddedResources.image("mygif.gif"); in About_Load() seems to pass data without error, but I am getting the following exception after loading the form, on the ShowDialog() method.

This is the code I am using (from a different form .. Form1 ) to load and display the About form.

private void button1_Click(object sender, EventArgs e)
{
    About frm = new About();
    frm.ShowDialog(this);
}

enter image description here

Why am I getting this exception, and what do I need to do to fix it so that my animated gif ( about 30 second loop ) can load ? (that is as small as I can get the loop and figured using an animated gif would be simpler than messing around with dated activex/com media controls or older directx framework to support video as a background and then have to mess with adding controls OVER the video -- big messy nightmare)

Stack Trace

   at System.Drawing.Image.SelectActiveFrame(FrameDimension dimension, Int32 frameIndex)
   at System.Drawing.ImageAnimator.ImageInfo.UpdateFrame()
   at System.Drawing.ImageAnimator.UpdateFrames(Image image)
   at System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
   at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Solution

  • Ok, I'm embarrassed that I did not catch this sooner. The issue is that by wrapping the Stream access in a using block, that the Stream is disposed on completion. I've seen this done before and always wondered about the consequence of it. Now I know the consequence.

    A simple fix, do not Dispose the stream.

    public class EmbeddedResources
    {
        public static Assembly self { get { return Assembly.GetExecutingAssembly(); } }
    
        public static Image image(string name)
        {
            Image result = null;
    
            // note: typeof(EmbeddedResources).Namespace will only work if EmbeddedResources is defined in the default namespace
            Stream res = self.GetManifestResourceStream(typeof(EmbeddedResources).Namespace + "." + name);
            result = Image.FromStream(res);
            return result;
        }
    
    }