我如何在后台计算DoWork事件,以便ReportProgress(百分比)将达到100%,progressBar1将到
本文关键字:百分比 将到 progressBar1 100% 以便 后台 计算 事件 DoWork ReportProgress | 更新日期: 2023-09-27 18:19:09
这就是我在DoWork事件和ProgressChanged
事件中所做的:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
double total = streamlength;
int counter = 0;
int percentage = 0;
BackgroundWorker bgw = (BackgroundWorker)sender;
int i = 0;
for (double x = 0; x < streamlength; x += dt)
{
streamDouble[0] = x;
SaveFramesFromVideo(strVideoFile, streamDouble, sf + i.ToString("D6") + ".bmp");
i++;
counter += 1;
percentage = counter * 100 / (int)total;
bgw.ReportProgress(percentage);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
我看到progressBar1的进度从左到右显示为绿色,但在中间,我在ProgressChanged
事件中得到异常:
ArgumentOutOfRangeException:值"133"对"Value"无效。"值"应该在"最小值"answers"最大值"之间。参数名称:值
错误行:progressBar1.Value = e.ProgressPercentage;
in The progressChanged
event.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ExtractFrames.Properties;
using ExtractFrames;
using JockerSoft.Media;
using JockerSoft;
using Interop.qedit;
using Interop;
using System.Runtime.InteropServices;
using System.IO;
namespace ExtractFrames
{
public partial class Form1 : Form
{
double dt;
FolderBrowserDialog fb;
OpenFileDialog openFileDialog1;
private bool _connect = false;
private bool _rightButton;
List<LinePoint> _points = null;
private float _circleWidth = 10;
DirectoryInfo dir1;
FileInfo[] fi;
double streamlength;
MediaDet mdd;
double x;
string sf;
double[] streamDouble ;
string strVideoFile;
public Form1()
{
InitializeComponent();
fb = new FolderBrowserDialog();
openFileDialog1 = new OpenFileDialog();
mdd = new MediaDet();
streamDouble = new double[1];
sf = @"d:'Frames'";
dir1 = new DirectoryInfo(sf);
fi = dir1.GetFiles("*.bmp");
if (fi.Length == 0)
{
trackBar1.Enabled = false;
}
else
{
trackBar1.Minimum = 0;
trackBar1.Maximum = fi.Length - 1;
trackBar1.Value = 0;//fi.Length - 1;
Bitmap newImage;
newImage = new Bitmap(fi[0].FullName);
pictureBox1.Image = newImage;
}
}
private void getFrameRate()
{
// Get framerate
MediaDet md = new MediaDet();
md.Filename = strVideoFile;
//md.CurrentStream = 0; // choose the video stream
x = md.FrameRate;
double i = md.StreamLength;
}
public static void SaveFramesFromVideo(string videoFile, double[] positions, string outputBitmapFiles)
{
if (videoFile == null)
throw new ArgumentNullException("videoFile");
double streamLength;
IMediaDet mediaDet = null;
try
{
_AMMediaType mediaType;
if (openVideoStream(videoFile, out mediaDet, out mediaType))
{
streamLength = mediaDet.StreamLength;
Size target = getVideoSize(mediaType);
int iteration = 0;
foreach (double position in positions)
{
iteration++;
string outputBitmapFile = string.Format(outputBitmapFiles, iteration);
mediaDet.WriteBitmapBits(position, target.Width, target.Height, outputBitmapFile);
}
}
}
catch (COMException)
{
throw new InvalidVideoFileException();
}
finally
{
if (mediaDet != null)
Marshal.ReleaseComObject(mediaDet);
}
return;
}
private static Size getVideoSize(_AMMediaType mediaType)
{
WinStructs.VIDEOINFOHEADER videoInfo = (WinStructs.VIDEOINFOHEADER)Marshal.PtrToStructure(mediaType.pbFormat, typeof(WinStructs.VIDEOINFOHEADER));
return new Size(videoInfo.bmiHeader.biWidth, videoInfo.bmiHeader.biHeight);
}
private static Size scaleToFit(Size target, Size original)
{
if (target.Height * original.Width > target.Width * original.Height)
target.Height = target.Width * original.Height / original.Width;
else
target.Width = target.Height * original.Width / original.Height;
return target;
}
private static Size scaleToFitSmart(Size target, Size original)
{
target = scaleToFit(target, original);
if (target.Width > original.Width || target.Height > original.Height)
return original;
return target;
}
private static bool openVideoStream(string videoFile, out IMediaDet mediaDet, out _AMMediaType aMMediaType)
{
mediaDet = new MediaDet();
//loads file
mediaDet.Filename = videoFile;
//gets # of streams
int streamsNumber = mediaDet.OutputStreams;
//finds a video stream
for (int i = 0; i < streamsNumber; i++)
{
mediaDet.CurrentStream = i;
_AMMediaType mediaType = mediaDet.StreamMediaType;
if (mediaType.majortype == JockerSoft.Media.MayorTypes.MEDIATYPE_Video)
{
//video stream found
aMMediaType = mediaType;
return true;
}
}
//no video stream found
Marshal.ReleaseComObject(mediaDet);
mediaDet = null;
aMMediaType = new _AMMediaType();
return false;
}
private bool LoadPictureAt(int nIndex, object c)
{
bool bRet = false;
if (nIndex >= 0 && nIndex < fi.Length)
{
if (c.Equals(trackBar1))
pictureBox1.Load(fi[nIndex].FullName);
bRet = true;
}
return bRet;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
LoadPictureAt(trackBar1.Value, sender);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_points != null)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (SolidBrush myBrush = new SolidBrush(Color.Red))
{
for (int i = 0; i < _points.Count; i++)
{
try
{
Point pt = _points[i].Point;
e.Graphics.FillEllipse(myBrush, new RectangleF(pt.X - _circleWidth / 2F, pt.Y - _circleWidth / 2F, _circleWidth, _circleWidth));
if (i > 0)
{
if (_points[i].Connected)
e.Graphics.DrawLine(Pens.Blue, _points[i - 1].Point, _points[i].Point);
}
}
catch ( Exception err)
{
textBox1.Text = err.ToString();
}
}
}
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (_points == null)
_points = new List<LinePoint>();
_points.Add(new LinePoint() { Point = new Point(e.X, e.Y), Connected = _connect });
pictureBox1.Invalidate();
}
if (e.Button == MouseButtons.Right)
{
_connect = !_connect;
_rightButton = true;
}
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
_points.Clear();
if (_rightButton && _points != null)
_points.Clear();
pictureBox1.Invalidate();
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
_rightButton = false;
}
public class LinePoint
{
public Point Point { get; set; }
public bool Connected { get; set; }
}
private void loadVideoToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.Title = "Select a video file";
openFileDialog1.InitialDirectory = "c:''";
openFileDialog1.FileName = null;
openFileDialog1.Filter = "Video Files|*.wmv;*.3gp;*.avi";
openFileDialog1.FilterIndex = 1;
openFileDialog1.RestoreDirectory = true;
DialogResult result1 = openFileDialog1.ShowDialog();
string file1 = openFileDialog1.FileName;
if (result1 == DialogResult.OK)
{
strVideoFile = file1;
mdd.Filename = strVideoFile;
streamlength = mdd.StreamLength;
dt = (double)1 / mdd.FrameRate;//(double)20; //mdd.FrameRate;
backgroundWorker1.RunWorkerAsync();
}
if (result1 == DialogResult.Cancel)
{
if (file1 == "")
{
}
}
}
private void changeExtractedFramesDirectoryToolStripMenuItem_Click(object sender, EventArgs e)
{
fb.Description = "Directory To Extract Frames";
DialogResult result = fb.ShowDialog();
string file1 = fb.SelectedPath;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
double total = streamlength;
int counter = 0;
int percentage = 0;
BackgroundWorker bgw = (BackgroundWorker)sender;
int i = 1;
for (double x = 0; x < total; x += dt)
{
streamDouble[0] = x;
SaveFramesFromVideo(strVideoFile, streamDouble, sf + i.ToString("D6") + ".bmp");
i++;
counter += 1;
//percentage = counter * 100 / (int)total;
percentage = (int)((x / streamlength) * 100.0);
bgw.ReportProgress(percentage);
}
bgw.ReportProgress(100);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//progressBar1.Value = e.ProgressPercentage;
progressBar1.Value = Math.Max(0, Math.Min(100, e.ProgressPercentage));
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
fi = dir1.GetFiles("*.bmp");
if (fi.Length == 0)
{
trackBar1.Enabled = false;
}
else
{
trackBar1.Enabled = true;
trackBar1.Minimum = 0;
trackBar1.Maximum = fi.Length - 1;
trackBar1.Value = 0;//fi.Length - 1;
Bitmap newImage;
newImage = new Bitmap(fi[0].FullName);
pictureBox1.Image = newImage;
}
}
}
}
我看不到变量streamlength
和dt
的声明。backgroundworker(顾名思义)在后台工作。所以你的程序是并行工作的,UI是反应性的,当后台工作人员工作时,流长度的值可能会改变。在这种情况下,for循环运行到另一端streamlength
,然后计算百分比(您将streamlength
存储在total
中并使用它进行计算)。第一种方法是这样更改方法backgroundWorker1_DoWork
:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
double total = streamlength;
int counter = 0;
int percentage = 0;
BackgroundWorker bgw = (BackgroundWorker)sender;
int i = 0;
for (double x = 0; x < total; x += dt)
{
streamDouble[0] = x;
SaveFramesFromVideo(strVideoFile, streamDouble, sf + i.ToString("D6") + ".bmp");
i++;
counter += 1;
percentage = counter * 100 / (int)total;
bgw.ReportProgress(percentage);
}
}
现在应该可以了,但是我强烈建议你重新考虑一下这个程序。
尝试进行以下更改。首先,将百分比的计算更改为:
percentage = (int)((x / streamlength) * 100.0);
使用x
而不是计数器。我要做这个改变,因为这是你实际用来循环的。
接下来,为了确保不会因为舍入错误而出现问题,可以将进度条的值赋值更改为:
progressBar1.Value = Math.Max(0, Math.Min(100, e.ProgressPercentage));
这将确保分配的值始终在0到100之间。