也許我需要一個計時器?
我希望在保存影像之前或保存之后但要一張一張地顯示影像。現在它只是在回圈,所以在回圈結束之前它根本不會顯示設計器。
using Accord.Video.FFMPEG;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;
namespace Extract_Frames
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
using (var vFReader = new VideoFileReader())
{
vFReader.Open(@"C:\Users\Chocolade 1972\Downloads\MyVid.mp4");
for (int i = 0; i < vFReader.FrameCount; i )
{
Bitmap bmpBaseOriginal = vFReader.ReadVideoFrame();
//bmpBaseOriginal.Save(@"d:\frames\frame" i ".bmp");
pictureBox1.Image = bmpBaseOriginal;
//bmpBaseOriginal.Dispose();
}
vFReader.Close();
}
}
}
}
它正在作業一段時間,但在一些影像之后它會拋出例外:
pictureBox1.Image = bmpBaseOriginal;
例外說該物件正在使用中。
System.InvalidOperationException: '物件當前正在使用中
uj5u.com熱心網友回復:
你的代碼應該是這樣的:
private readonly Queue<Image> images = new Queue<Image>();
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
using (var vFReader = new VideoFileReader())
{
vFReader.Open(@"C:\Users\Chocolade 1972\Downloads\MyVid.mp4");
for (var i = 0; i < vFReader.FrameCount; i )
{
images.Enqueue(vFReader.ReadVideoFrame());
}
// Not sure that this would be required as it might happen implicitly at the end of the 'using' block.
vFReader.Close();
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pictureBox1.Image = images.Dequeue();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Image.Dispose();
var image = images.Dequeue();
pictureBox1.Image = image;
if (images.Count == 0)
{
timer1.Stop();
}
}
所有的Images都被添加到一個佇列中,然后一個一個地出隊。加載完成后立即顯示第一個,其余的將定期顯示。該代碼每次顯示Image一次,然后銷毀并丟棄它。如果您想在到達最后一個時再次顯示它們,那么您可以使用不同型別的集合并在到達結尾時回傳到開頭。
編輯:
我可能誤解了你的要求。此代碼應Images在生成時顯示:
private void Form1_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
using (var vFReader = new VideoFileReader())
{
vFReader.Open(@"C:\Users\Chocolade 1972\Downloads\MyVid.mp4");
for (var i = 0; i < vFReader.FrameCount; i )
{
backgroundWorker1.ReportProgress(0, vFReader.ReadVideoFrame());
}
// Not sure that this would be required as it might happen implicitly at the end of the 'using' block.
vFReader.Close();
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pictureBox1.Image?.Dispose();
pictureBox1.Image = (Image)e.UserState;
}
你可以拋棄Timer和Queue。我唯一擔心的是,這可能會導致OutOfMemoryException. GC.Collect如果是這樣,您可以間歇性地呼叫顯式呼叫,例如每 100 幀。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/522149.html
標籤:C#表格
