C# Progressbar, переполнение возвращает отрицательное значение
Я создаю приложение для резервного копирования. У меня есть 5 папок в разных местах, что нужно скопировать в одну резервную папку. (решено с помощью checkbox.checked) Основная проблема заключается в том, что некоторые из папок имеют общий объем более 3-4 ГБ (со всеми подпапками). Прогрессбар не обновляется, поскольку "maxbyte" возвращает отрицательное значение. (Я предполагаю, что int32 переполняется после копирования файла 2 ГБ) (Извините, я не могу объяснить это более подробно.. Я всего лишь начинающий программист на C#)
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using memoQClientBackuTool;
namespace memoQBackupTool
{
public partial class BGWorker : Form
{
public BGWorker()
{
InitializeComponent();
}
BackgroundWorker bw;
string source = "";
string target = "";
bool isfile = false;
int filecount = 0;
int currentFileNr = 1;
string newFilename = "";
int maxbytes = 0;
public void ShowProgress(string from, string to, bool isf)
{
InitializeComponent();
source = from;
target = to;
isfile = isf;
bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
GetFileData();
}
private void GetFileData()
{
if (isfile)
{
FileInfo fi = new FileInfo(source);
maxbytes = Convert.ToInt32(fi.Length);
//
//set progress bar length
//
progressBar1.Minimum = 0;
progressBar2.Minimum = 0;
progressBar1.Maximum = maxbytes;
progressBar2.Maximum = 1;
bw.RunWorkerAsync();
}
else
{
GetDirectoryInfo(source);
//
//set progress bar length
//
progressBar1.Minimum = 0;
progressBar2.Minimum = 0;
progressBar1.Maximum = maxbytes;
progressBar2.Maximum = filecount;
bw.RunWorkerAsync();
}
}
private void GetDirectoryInfo(string source)
{
string[] files = Directory.GetFiles(source);
foreach (string file in files)
{
FileInfo fi = new FileInfo(file);
maxbytes += Convert.ToInt32(fi.Length);
filecount += 1;
}
string[] folders = Directory.GetDirectories(source);
foreach (string folder in folders)
{
GetDirectoryInfo(folder);
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (isfile)
{
FileStream fs = new FileStream(source, FileMode.Open);
long FileSize = fs.Length;
FileInfo fi = new FileInfo(source);
byte[] bBuffer = new byte[(int)FileSize];
fs.Read(bBuffer, 0, (int)FileSize);
fs.Close();
UpdateLabels(fi.FullName);
newFilename = fi.Name;
try
{
FileStream fss = new FileStream(target + "\\" + newFilename, FileMode.CreateNew);
BinaryWriter biwr = new BinaryWriter(fss);
for (int i = 0; i < bBuffer.Length; i += 15000)
{
if (i + 15000 < bBuffer.Length)
{
biwr.Write(bBuffer, i, 15000);
bw.ReportProgress(15000);
}
else
{
biwr.Write(bBuffer, i, bBuffer.Length - i);
bw.ReportProgress(bBuffer.Length - i);
}
}
biwr.Close();
fss.Close();
} catch (IOException){
MessageBox.Show("Nincs olyan...");
}
}
else
{
string[] temp = source.Split('\\');
target += "\\" + temp[temp.Count() - 1];
DirectoryInfo s = new DirectoryInfo(source);
DirectoryInfo t = new DirectoryInfo(target);
CopyDirectory(s, t);
}
if (bw.CancellationPending)
{
e.Cancel = true;
return;
}
}
public void CopyDirectory(DirectoryInfo di_source, DirectoryInfo di_target)
{
if (Directory.Exists(di_target.FullName) == false)
{
Directory.CreateDirectory(di_target.FullName);
}
foreach (FileInfo fi in di_source.GetFiles())
{
newFilename = fi.Name;
FileStream fs = new FileStream(fi.FullName, FileMode.Open);
long FileSize = fs.Length;
byte[] bBuffer = new byte[(int)FileSize];
fs.Read(bBuffer, 0, (int)FileSize);
fs.Close();
UpdateLabels(fi.FullName);
if (File.Exists(di_target.ToString() + "\\" + fi.Name))
{
Random rand = new Random();
newFilename = newFilename + "_" + rand.Next(1, 10000);
}
FileStream fss = new FileStream(di_target.ToString() + "\\" + newFilename, FileMode.CreateNew);
BinaryWriter biwr = new BinaryWriter(fss);
for (int i = 0; i < bBuffer.Length; i += 500000)
{
if (i + 500000 < bBuffer.Length)
{
biwr.Write(bBuffer, i, 500000);
bw.ReportProgress(500000);
}
else
{
biwr.Write(bBuffer, i, bBuffer.Length - i);
bw.ReportProgress(bBuffer.Length - i);
}
}
biwr.Close();
fss.Close();
}
foreach (DirectoryInfo di_SourceSubDir in di_source.GetDirectories())
{
DirectoryInfo nextSubDir = di_target.CreateSubdirectory(di_SourceSubDir.Name);
CopyDirectory(di_SourceSubDir, nextSubDir);
}
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value += e.ProgressPercentage;
int copied = progressBar1.Value / 1024;
int total = maxbytes / 1024;
lbl_kbscopied.Text = copied + "/" + total;
}
delegate void UpdateLabelsDelegate(string filename);
void UpdateLabels(string fname)
{
if (!InvokeRequired)
{
lbl_filename.Text = "Copying: " + fname;
lbl_filenr.Text = "File: " + currentFileNr + "/" + filecount;
currentFileNr++;
progressBar2.Value += 1;
}
else
{
Invoke(new UpdateLabelsDelegate(UpdateLabels), new object[] { fname });
}
}
private void button1_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
bw.CancelAsync();
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
Cursor.Current = Cursors.Default;
CustomMsgBox.Show("The task has been canceled", "Error", "OK");
this.Close();
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
}
else
{
this.Close();
}
}
}
}
2 ответа
Отчет о прогрессе не в абсолютных значениях, а в относительных; процент, например.
Допустим, файл размером 1 МБ занимает 100% индикатора выполнения. Это означает, что вы должны инициализировать его с 100: progressBar1.Maximum = 100
, Тогда каждые 15000 байтов, которые были скопированы, немного больше 1%. Вместо bw.ReportProgress(15000)
делать bw.ReportProgress(1)
,
Я предлагаю использовать long вместо int везде, где вы копируете/загружаете общее количество байтов. Если я понял ваш код, вы используете int в цикле for, где вы вызываете ReportProgress