【问题标题】:Why when looping in timer tick event over images list it's throwing exception parameter is not valid?为什么在图像列表上循环计时器滴答事件时抛出异常参数无效?
【发布时间】:2021-10-09 08:14:21
【问题描述】:

System.ArgumentException: '参数无效。'

private void timer1_Tick(object sender, EventArgs e)
        { 
            for (int i = 0; i < myGifList.Count; i++)
            {
                Bitmap bmp = new Bitmap(myGifList[i]);
                pictureBox1.Image = bmp;
                bmp.Dispose();
            }
        }

循环结束后抛出异常。

在那之前我做过:

private void timer1_Tick(object sender, EventArgs e)
        { 
            for (int i = 0; i < myGifList.Count; i++)
            {
                pictureBox1.Image = new Bitmap(myGifList[i]);
            }
        }

然后它抛出内存异常。

在那之前我第一次尝试这个:

int counter = 0;
        private void timer1_Tick(object sender, EventArgs e)
        {
            if(counter == 10)
            {
                counter = 0;
            }

            for (int i = 0; i < myGifList.Count; i++)
            {
                Bitmap bmp = new Bitmap(myGifList[counter]);
                pictureBox1.Image = bmp;
            }

            counter++;
        }

这正在工作,图像在pictureBox1中循环,但一段时间后它会抛出内存不足异常。

完整代码:

我正在下载图像,然后将图像读回列表,然后尝试在 picutreBox1 中显示它们,并使用 trackBar1 通过计时器更改 pictureBox1 中图像的循环速度。

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.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Extract
{
    public partial class Form1 : Form
    {
        List<string> myGifList = new List<string>();

        public Form1()
        {            
            List<string> times = new List<string>();
            string t = "";

            InitializeComponent();

            using (WebClient client = new WebClient()) // WebClient class inherits IDisposable
            {
                client.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36");
                client.DownloadFile("https://myimages/", @"D:\localfile.html");

                var file = File.ReadAllText(@"D:\localfile.html");

                int idx = file.IndexOf("arrayImageTimes.push");
                int idx1 = file.IndexOf("</script>", idx);

                string results = file.Substring(idx, idx1 - idx);

                var statements = results.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < statements.Length; i++)
                {
                    if (i == 10)
                    {
                        break;
                    }

                    string number = statements[i].Split('\'')[1];

                    times.Add(number); // add to a list instead

                    var link = "https://myimages" + number;
                    client.DownloadFile(link, @"D:\Images\Image" + i + ".jpeg");
                }
            }

            FileInfo[] fi;
            DirectoryInfo dir1 = new DirectoryInfo(@"D:\Images");
            fi = dir1.GetFiles("*.jpeg");
            for (int i = 0; i < fi.Length; i++)
            {
                myGifList.Add(fi[i].FullName);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        int counter = 0;
        private void timer1_Tick(object sender, EventArgs e)
        {
            if(counter == 10)
            {
                counter = 0;
            }

            for (int i = 0; i < myGifList.Count; i++)
            {
                Bitmap bmp = new Bitmap(myGifList[counter]);
                pictureBox1.Image = bmp;
            }

            counter++;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            timer1.Interval = 100 * trackBar1.Value;
        }
    }
}

【问题讨论】:

  • 但是你为什么要运行循环并设置相同的控件?
  • 这个循环将在几毫秒内完成。除了最后一张之外,您将无法看到其他图像。你到底想达到什么目的?旁注:您不需要每次想要在图片框中显示新的位图时都初始化它。
  • 如果您尝试在特定时间间隔内迭代图像,请去掉最后一个解决方案中的 for 循环并保留 counter 变量。但不是检查counter == 10,而是检查counter == GifList.Count

标签: c# winforms


【解决方案1】:

您似乎在尝试循环遍历 myGifList,但随后您在方法中硬编码了 10 的值。

然而,更大的问题是你甚至没有使用循环定义的i,所以你只是重写了相同的BitmapmyGifList.Count 次,毫无意义——这使你的代码效率低下。

试试:

private void timer1_Tick(object sender, EventArgs e)
{
   if (counter == myGifList.Count)
      counter = 0;

   pictureBox1.Image?.Dispose();

   Bitmap bmp = new Bitmap(myGifList[counter]);
   pictureBox1.Image = bmp;

   counter++;
}

请注意,您应该使用null conditional operator ? 来防止在调用.Dispose() 时可能出现NullReferenceException

pictureBox1.Image?.Dispose();

第一次将图像设置为pictureBox1.Image 时会发生这种情况@ 987654335@,导致.Dispose() 抛出异常。


更好的是使用PictureBox.ImageLocation 属性,它允许您显示图像而无需每次都创建Bitmap 对象:

private void timer1_Tick(object sender, EventArgs e)
{
   if (counter == myGifList?.Count)
      counter = 0;

   pictureBox1.ImageLocation = myGifList[counter];

   counter++;
}

旁注:Timer.Interval 属性也在 milliseconds 中,所以如果你想真正看到循环播放的图像,我会提高 100trackBar1_Scroll(...) 中的值。

【讨论】:

  • 建议ImageLocation 属性是好事。在位图示例中,只需记住在创建新的 bmp 之前处理掉之前的 bmp:pictureBox1.Image?.Dispose();
  • @VisualVincent 是的,更新的答案 - 谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多