Экран рекордера падает при перемещении окна формы - PullRequest
0 голосов
/ 29 августа 2018

Я следил за кучей уроков и сделал экранный рекордер. Он работает, снимая скриншот, а затем используя AForge.video аддон, чтобы преобразовать его в формат avi. Программа работала нормально, но памяти не хватило примерно через 20 секунд. Это может привести к сбою программы или к самопроизвольному всплеску лага. Чтобы остановить это, я добавил метод удаления в конце каждого скриншота, чтобы очистить память. Это снизило использование памяти, однако делает приложение крайне нестабильным. Когда я перемещаю главное окно или жду примерно 3 минуты на запись, программа вылетает и показывает это:
Скриншот ошибки

Каждый раз, когда я удаляю методы удаления, программа работает нормально, но быстро исчерпывает память. Может быть, я просто неправильно использую метод dispose.

Вот код, который дает сбой программе. Есть много кода, чтобы включить все это.

 counter = 0;
 imagelist = new Bitmap[100000];
 Globals.imgcount = 0;
 Graphics g;

 basePath = sel.ToString();
 basePath = @"C:\Users\sim\Videos\Captures";
 using (var videowriter = new VideoFileWriter())
 {
     videowriter.Open(basePath + "timelapse.avi", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, 9, VideoCodec.MPEG4, 1200000);

     while (Globals.recording == true) 
     {
         try
         {                       
             try
             {                      
                 //takes the screenshot                            
                 bm = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                 //turns it into graphics
                 g = Graphics.FromImage(bm);
                 g.CopyFromScreen(0, 0, 0, 0, bm.Size);

                 counter++;                                    

                 videowriter.WriteVideoFrame(bm);

                 //display image
                 Bitmap original = bm;
                 Bitmap resized2 = new Bitmap(original, new Size(pictureBox1.Width, pictureBox1.Height));
                 bm = resized2;

                 pictureBox1.Image = bm;                                                       

                 Thread.Sleep(10);

                 if (/*counter % 18 == 0*/ true) 
                 {
                    try
                    {
                        g.Dispose();
                        bm.Dispose();

                        original.Dispose();
                        resized2.Dispose();
                    }
                    catch
                    {
                        MessageBox.Show("Disposal error");
                    }
                }
            }
            catch { }
        }
        catch { }
    }                
    videowriter.Close();
}

Я надеюсь, что этой информации достаточно, чтобы что-то выяснить. Спасибо всем, кто может помочь.

1 Ответ

0 голосов

Вы делаете много ненужных вещей, например, создаете 3 растровых изображения вместо одного, устанавливаете изображение bm на picbox и, конечно, запускаете код для основного пользовательского интерфейса. Конечно, это замерзнет. Для простого и быстрого исправления создайте таймер. Установите интервал 10. Создайте button, который остановит таймер, и тот, который запустит его и запишет. В таймере вместо звонка неоднократно

pictureBox1.Image = bm;

использование

pictureBox1.Invalidate();

Код:

//not good names. change it to something meaningfull
private Bitmap bm;
private Graphics g;
VideoFileWriter videowriter;

private void timer1_Tick( object sender, EventArgs e ) {;
    //takes the screenshot                            
    g.CopyFromScreen( 0, 0, 0, 0, bm.Size );

    videowriter.WriteVideoFrame(bm);

    pictureBox1.Invalidate();
}

Кнопка, с которой начинается запись:

private void Start_Click( object sender, EventArgs e ) {
    //create both bitmap and graphics once!
    bm = new Bitmap( Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height );
    g = Graphics.FromImage( bm );

    pictureBox1.Image = bm; //Just once!

    basePath = sel.ToString();
    basePath = @"C:\Users\sim\Videos\Captures";
    videowriter = new VideoFileWriter();
    videowriter.Open(basePath + "timelapse.avi", Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, 9, VideoCodec.MPEG4, 1200000);

    timer1.Enabled = true;
}

Кнопка остановки записи:

private void Stop_Click( object sender, EventArgs e ) {
    timer1.Enabled = false;

    pictureBox1.Image = null;
    bm.Dispose();
    bm = null;
    g.Dispose();
    g = null;
    videowriter.Close();
    //I don't know if videowriter can be disposed if so dispose it too and set it to null
}

Также установите picturebox SizeMode в StreachImage

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...