我使用以下代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; using System.IO; namespace WindowsApplication1 { public partial class Form1 : Form { // Class to report progress private class UIProgress { public UIProgress(string name_, long bytes_, long maxbytes_) { name = name_; bytes = bytes_; maxbytes = maxbytes_; } public string name; public long bytes; public long maxbytes; } // Class to report exception { private class UIError { public UIError(Exception ex, string path_) { msg = ex.Message; path = path_; result = DialogResult.Cancel; } public string msg; public string path; public DialogResult result; } private BackgroundWorker mCopier; private delegate void ProgressChanged(UIProgress info); private delegate void CopyError(UIError err); private ProgressChanged OnChange; private CopyError OnError; public Form1() { InitializeComponent(); mCopier = new BackgroundWorker(); mCopier.DoWork += Copier_DoWork; mCopier.RunWorkerCompleted += Copier_RunWorkerCompleted; mCopier.WorkerSupportsCancellation = true; OnChange += Copier_ProgressChanged; OnError += Copier_Error; button1.Click += button1_Click; ChangeUI(false); } private void Copier_DoWork(object sender, DoWorkEventArgs e) { // Create list of files to copy string[] theExtensions = { "*.jpg", "*.jpeg", "*.bmp", "*.png", "*.gif" }; List<FileInfo> files = new List<FileInfo>(); string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); DirectoryInfo dir = new DirectoryInfo(path); long maxbytes = 0; foreach (string ext in theExtensions) { FileInfo[] folder = dir.GetFiles(ext, SearchOption.AllDirectories); foreach (FileInfo file in folder) { if ((file.Attributes & FileAttributes.Directory) != 0) continue; files.Add(file); maxbytes += file.Length; } } // Copy files long bytes = 0; foreach (FileInfo file in files) { try { this.BeginInvoke(OnChange, new object[] { new UIProgress(file.Name, bytes, maxbytes) }); File.Copy(file.FullName, @"c:\temp\" + file.Name, true); } catch (Exception ex) { UIError err = new UIError(ex, file.FullName); this.Invoke(OnError, new object[] { err }); if (err.result == DialogResult.Cancel) break; } bytes += file.Length; } } private void Copier_ProgressChanged(UIProgress info) { // Update progress progressBar1.Value = (int)(100.0 * info.bytes / info.maxbytes); label1.Text = "Copying " + info.name; } private void Copier_Error(UIError err) { // Error handler string msg = string.Format("Error copying file {0}\n{1}\nClick OK to continue copying files", err.path, err.msg); err.result = MessageBox.Show(msg, "Copy error", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation); } private void Copier_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // Operation completed, update UI ChangeUI(false); } private void ChangeUI(bool docopy) { label1.Visible = docopy; progressBar1.Visible = docopy; button1.Text = docopy ? "Cancel" : "Copy"; label1.Text = "Starting copy..."; progressBar1.Value = 0; } private void button1_Click(object sender, EventArgs e) { bool docopy = button1.Text == "Copy"; ChangeUI(docopy); if (docopy) mCopier.RunWorkerAsync(); else mCopier.CancelAsync(); } } }
复制文件并在进度条中显示状态时,将其张贴在此处( nobugz 张贴在此处)。
我想在复制(尤其是大文件)时不断增加进度条的值。此示例代码中发生的是,进度条上的值在每个复制的文件上停止,并且在复制了一个文件之后,它将递增到下一个要复制的文件的大小。我希望它能像CopyFileEx在Windows中一样工作,在复制时进度条会不断增加(我无法使用,CopyFileEx因为我想拥有自己的实现)。
CopyFileEx
您需要这样的东西:
public delegate void ProgressChangeDelegate(double Persentage, ref bool Cancel); public delegate void Completedelegate(); class CustomFileCopier { public CustomFileCopier(string Source, string Dest) { this.SourceFilePath = Source; this.DestFilePath = Dest; OnProgressChanged += delegate { }; OnComplete += delegate { }; } public void Copy() { byte[] buffer = new byte[1024 * 1024]; // 1MB buffer bool cancelFlag = false; using (FileStream source = new FileStream(SourceFilePath, FileMode.Open, FileAccess.Read)) { long fileLength = source.Length; using (FileStream dest = new FileStream(DestFilePath, FileMode.CreateNew, FileAccess.Write)) { long totalBytes = 0; int currentBlockSize = 0; while ((currentBlockSize = source.Read(buffer, 0, buffer.Length)) > 0) { totalBytes += currentBlockSize; double persentage = (double)totalBytes * 100.0 / fileLength; dest.Write(buffer, 0, currentBlockSize); cancelFlag = false; OnProgressChanged(persentage, ref cancelFlag); if (cancelFlag == true) { // Delete dest file here break; } } } } OnComplete(); } public string SourceFilePath { get; set; } public string DestFilePath { get; set; } public event ProgressChangeDelegate OnProgressChanged; public event Completedelegate OnComplete; }
只需在单独的线程中运行它并订阅OnProgressChanged事件即可。
OnProgressChanged