Concurrent file access - c#

I am running multiple instances of an application that reads first line from a file, then it deletes the first line and saves the file under the same name. I found out that in some instances the applications will crash. I created a sample program just to better understand the issues I have.
If I run four instances of this program, sometimes multiple instances attempt to delete the same line. In the end the operation succeeds, but it is not efficient. How can I improve the code to avoid this? Perhaps each instance needs to lock the file while it uses it.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace ConcurrentFileAccess
{
public partial class MainForm : Form
{
bool gbAbort = false;
public MainForm()
{
InitializeComponent();
}
void BtnCreateFileClick(object sender, EventArgs e)
{
string sFile = #"S:\Temp\concurrentFileAccess.txt";
Stopwatch stopwatch = Stopwatch.StartNew();
if (File.Exists(sFile)) {
File.Delete(sFile);
}
if (!File.Exists(sFile)) {
List<string> list = new List<string>();
var fc = File.Create(sFile);
fc.Close();
for (int i = 1; i <= 200; i++) {
list.Add(i.ToString());
}
File.WriteAllLines(sFile, list);
listBox1.Items.Add("File " + sFile + " was created and it contains 200 lines");
} else {
string[] lines = File.ReadAllLines(sFile);
int nlines = lines.Length;
listBox1.Items.Add("File " + sFile + " already exists and it contains " + nlines + " lines");
}
stopwatch.Stop();
listBox1.Items.Add("File created in " + stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.fff"));
}
void BtnDeleteFromFileClick(object sender, EventArgs e)
{
gbAbort = false;
int nlines = 9999;
while (nlines > 0) {
nlines = DeleteOneLine();
Application.DoEvents();
if (gbAbort) {
return;
}
}
}
int DeleteOneLine()
{
string sFile = #"S:\Temp\concurrentFileAccess.txt";
listBox1.Items.Add("We are in DeleteLines()...");
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
int nLinesLeft = 9999;
string line0 = string.Empty;
Stopwatch stopwatch = Stopwatch.StartNew();
int ntry = 0;
while (ntry < 100) {
try {
string[] lines = File.ReadAllLines(sFile);
List<string> list = new List<string>(lines);
nLinesLeft = list.Count;
if (nLinesLeft > 0) {
line0 = list[0];
list.RemoveAt(0);
listBox1.Items.Add("Deleted line " + line0);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
listBox1.Items.Add("Writing to file after line " + line0 + " was deleted");
File.WriteAllLines(sFile, list);
nLinesLeft = list.Count;
Application.DoEvents();
} else {
nLinesLeft = 0;
break;
}
} catch (Exception) {
ntry++;
listBox1.Items.Add("ntry = " + ntry + ", could not delete line " + line0 + " from file. Attempting again...");
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
Application.DoEvents();
Thread.Sleep(50);
}
}
if(ntry >= 100) {
nLinesLeft = -1; // should never get here
}
stopwatch.Stop();
listBox1.Items.Add("ntry: " + ntry + ", lines Left: " + nLinesLeft + ", elapsed = " + stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.fff"));
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
return nLinesLeft;
}
void BtnAbortClick(object sender, EventArgs e)
{
gbAbort = true;
}
void BtnOpenAppFolderClick(object sender, EventArgs e)
{
string sFile = Application.ExecutablePath;
string sPath = Path.GetDirectoryName(sFile);
Process.Start(sPath);
}
void BtnOpenFileClick(object sender, EventArgs e)
{
string sFile = #"S:\Temp\concurrentFileAccess.txt";
if(File.Exists(sFile)) {
Process.Start(sFile);
}
else {
MessageBox.Show("File " + sFile + " not found");
}
}
}
}

Related

C# Starting process with args in specific folder

I am trying to decompile over 30k vulkan shader files using shaderc from google.
All shaders are located in "C:\Users\Admin\Desktop\NMS MOD\SHADER MOD\v2.41\PC"
The tool used to decompile is spirv-cross.exe which I added to Windows Environment variables, which lets me run this simple bat file inside the shaders folder and works fine.
"spirv-cross --version 450 --vulkan-semantics --stage frag ATMOSPHERE_FRAG_CLOUD_769.SPV > ATMOSPHERE_FRAG_CLOUD_769.GLSL"
Since there is way too many to do this manually. I want to make a simple App to do this process and also get the stage type from file name (in this case "frag").
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace Lazy_Me_3
{
public partial class Form1 : Form
{
public string PATH;
public string[] sFilesNames;
public int totalcount = 0;
public int currentcount = 0;
public Form1()
{
InitializeComponent();
}
private string GetStageType(string filename)
{
// Valid Stages = vertex, vert, fragment, frag, tesscontrol, tesc, tesseval, tese, geometry, geom, compute, comp
if (filename.Contains("_VERTEX_") || filename.Contains("_VERT_")) return "vert";
if (filename.Contains("_FRAGMENT_") || filename.Contains("_FRAG_")) return "frag";
if (filename.Contains("_TESSCONTROL_") || filename.Contains("_TESC_")) return "tesc";
if (filename.Contains("_TESSEVEL_") || filename.Contains("_TESE_")) return "tese";
if (filename.Contains("_GEOMETRY_") || filename.Contains("_GEOM_")) return "geom";
if (filename.Contains("_COMPUTE_") || filename.Contains("_COMP_")) return "comp";
else return "error";
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < sFilesNames.Count(); i++)
{
sFilesNames[i] = Path.GetFileName(sFilesNames[i]);
if (sFilesNames[i].Length > 1)
{
var newName = sFilesNames[i].Substring(0, sFilesNames[i].Length - 4);
sFilesNames[i] = newName;
}
}
foreach (var file in sFilesNames)
{
string stageType = GetStageType(file);
if (stageType != "error")
{
string args = "--version 450 --vulkan-semantics --stage " + stageType + " " + file + ".SPV" + " > " + file + ".GLSL";
Process process = new Process();
process.StartInfo.FileName = "spirv-cross";
process.StartInfo.Arguments = args;
process.StartInfo.WorkingDirectory = PATH;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit(5000);
currentcount += 1;
label1.Text = "Status : " + currentcount.ToString() + " / " + totalcount.ToString();
}
else MessageBox.Show("Error on finding stage type of file : " + file);
}
}
private void button2_Click(object sender, EventArgs e)
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
sFilesNames = Directory.GetFiles(fbd.SelectedPath, "*.SPV");
totalcount = sFilesNames.Length;
PATH = fbd.SelectedPath;
label3.Text = "Directory : " + PATH;
label2.Text = "Total Count : " + totalcount.ToString();
label1.Text = "Status : 0 / " + totalcount.ToString();
button1.Enabled = true;
}
}
}
}
}
EDIT 1 : Bodge using cmd that works
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < sFilesNames.Count(); i++)
{
//sFilesNames[i] = Path.GetFileName(sFilesNames[i]);
if (sFilesNames[i].Length > 1)
{
var newName = sFilesNames[i].Substring(0, sFilesNames[i].Length - 4);
sFilesNames[i] = newName;
}
}
foreach (var file in sFilesNames)
{
string stageType = GetStageType(file);
if (stageType != "error")
{
var p = new ProcessStartInfo("cmd", #"/c spirv-cross --version 450 --vulkan-semantics --stage " + stageType + " " + file + ".SPV" + " > " + file + ".GLSL");
p.UseShellExecute = false;
p.CreateNoWindow = true;
var ps = Process.Start(p);
ps.WaitForExit();
currentcount += 1;
label1.Text = "Status : " + currentcount.ToString() + " / " + totalcount.ToString();
}
else
{
errorcount += 1;
label4.Text = "Errors : " + errorcount.ToString();
}
}
}

c# Progressbar, Overflow returns negative value

I'm creating a backup application. I have 5 folders in different locations what needs to be copied to one backup folder. (solved via checkbox.checked)
The main issue is that some of the folders are more than 3-4GB in total (with all subfolders) Progressbar is not updated because "maxbyte" returns a negative value. (I assume int32 overflows after 2gb file copy)
(Sorry can't explain it more in details..I'm just a beginner C# programmer)
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();
}
}
}
}
Report progress not in absolute values, but in relative; percentage, for example.
Let say that 1MB file is 100% of progress bar. That means that you have to initialize it with 100: progressBar1.Maximum = 100. Then every 15000 bytes that were copied is a little bit more than 1%. Instead of bw.ReportProgress(15000) do bw.ReportProgress(1).
I will suggest to use long instead of int wherever you are getting total bytes copied/uploaded so far. If I understood your code you are using int in for loop where you call ReportProgress

Multithread using backgroundworker and event handler

I'm developing a sample program to connect multiple device using backgroundworker. Each device connected will be add to the list as new object. After finished connecting all the devices, i wanted to add an event handler for each connected devices. The problem that i'm facing now is the event handler doesn't firing at all. Below are the sample codes.
The Connect click button event :
private void btnConnect_Click(object sender, EventArgs e)
{
using (BackgroundWorker m_oWorker = new BackgroundWorker())
{
m_oWorker.DoWork += delegate (object s, DoWorkEventArgs args)
{
int iIpStart = 0;
int iIpEnd = 0;
string strIp1 = string.Empty;
string strIp2 = string.Empty;
list.Clear();
string[] sIP1 = txtIpStart.Text.Trim().ToString().Split('.');
string[] sIP2 = txtIpEnd.Text.Trim().ToString().Split('.');
iIpStart = Convert.ToInt32(sIP1[3]);
iIpEnd = Convert.ToInt32(sIP2[3]);
strIp1 = sIP1[0] + "." + sIP1[1] + "." + sIP1[2] + ".";
strIp2 = sIP2[0] + "." + sIP2[1] + "." + sIP2[2] + ".";
Ping ping = new Ping();
PingReply reply = null;
int iIncre = 0;
int iVal = (100 / (iIpEnd - iIpStart));
for (int i = iIpStart; i <= iIpEnd; i++)
{
Thread.Sleep(100);
string strIpconnect = strIp1 + i.ToString();
Console.Write("ip address : " + strIpconnect + ", status: ");
reply = ping.Send(strIpconnect);
if (reply.Status.ToString() == "Success")
{
if (ConnectDevice(strIpconnect))
{
strLastDevice = strIpconnect + " Connected";
isconnected = true;
}
else
{
isconnected = false;
}
}
else
{
isconnected = false;
}
m_oWorker.ReportProgress(iIncre);
iIncre = iIncre + iVal;
}
m_oWorker.ReportProgress(100);
};
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
m_oWorker.RunWorkerAsync();
}
}
ConnectDevice function method. Connected device will be added to the list :
protected bool ConnectDevice(string sIP)
{
try
{
NewSDK sdk = new NewSDK();
if (sdk.Connect() == true)
{
list.Add(new objSDK { sdk = sdk, ipaddress = sIP });
return true;
}
else
{
}
}
catch() {}
return false;
}
the Backgroundworker :
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
btnListen.Enabled = true;
}
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
if (isconnected)
{
listBox2.Items.Add(strLastDevice);
string[] ssplit = sDeviceInfo.Split(';');
foreach (string sword in ssplit)
{
listBox1.Items.Add(sword);
}
}
}
The function to attached event :
private void RegisterEvent()
{
foreach (objSDK obj in list)
{
obj.sdk.OnTransaction += () =>
{
listBox1.Items.Add("ip : " + obj.IP + " transaction");
};
}
}
You have declared m_oWorker as a local variable. I'm guessing this was a mistake ( the m_ prefix should only be used for class member variables)?
Also, you declared it within a using statement, meaning that it that the framework will call Dispose() on it at the end of the using block. Even if you held on to a reference to it (and I don't think you do) it still means its resources will be deallocated, which is probably why it isn't handling any events.
I try another workaround by using thread and task and work perfectly. Thanks for all response

How can i sum a changing values in int variable ? And what is the real number of directories on hard disk?

Backgroundworker dowork event
string CurrentFileWithPath;
private void _FileProcessingWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
DirectoryInfo[] MySubDirectories = (DirectoryInfo[])e.Argument;
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
{
DirectoryInfo MySubDirectory = MySubDirectories[i];
List<FileInfo> l = new List<FileInfo>();
CountFiles(MySubDirectory, l);
int totalFiles = l.Count;
object[] CurrentStatus = new object[5];
CurrentStatus[3] = i.ToString();
CurrentStatus[4] = totalFiles.ToString();
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
string CurrentDirectory = "Current Directory: " + MySubDirectory.Name;
foreach (FileInfo MyFile in l)
{
CurrentStatus = new object[5];
if (_FileProcessingWorker.CancellationPending)
{
e.Cancel = true;
return;
}
if (MyFile.Extension.ToLower() == ".cs" || MyFile.Extension.ToLower() == ".vb")
{
string CurrentFile = "Current File: " + MyFile.Name;
string CurrentFileWithPath = MyFile.FullName;
CurrentStatus[0] = CurrentDirectory;
CurrentStatus[1] = CurrentFile;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
List<string> Result = SearchInFile(CurrentFileWithPath, "static class FileShellExtension");
if (Result != null && Result.Count > 0)
{
CurrentStatus[2] = Result;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
}
}
}
}
}
catch (Exception err)
{
return;
}
Progresschanged event
private void _FileProcessingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (typeof(object[]) == e.UserState.GetType())
{
object[] StatusMsg = (object[])e.UserState;
if (5 == StatusMsg.GetLength(0))
{
label2.Text = StatusMsg[4].ToString();
label4.Text = StatusMsg[3].ToString();
if (StatusMsg[0] != null && StatusMsg[1] != null)
{
lblCurrentDirectory.Text = StatusMsg[0].ToString();
lblStatus.Text = StatusMsg[1].ToString();
}
if (StatusMsg[2] != null)
{
if (StatusMsg[2].GetType() == typeof(List<string>))
{
List<string> l = (List<string>)StatusMsg[2];
for (int i = 0; i < l.Count; i++)
{
ListViewCostumControl.lvnf.Items.Add("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
w.WriteLine("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
}
}
}
}
}
}
CountFiles method
private void CountFiles(DirectoryInfo di, List<FileInfo> l)
{
try
{
l.AddRange(di.EnumerateFiles());
}
catch
{
string fff = "";
}
try
{
IEnumerable<DirectoryInfo> subDirs = di.EnumerateDirectories();
if (subDirs.Count() > 0)
{
foreach (DirectoryInfo dir in subDirs)
CountFiles(dir, l);
}
}
catch
{
string yyy = "";
}
}
SearchInFile method
private List<string> SearchInFile(string fileToSearch, string textToSearch)
{
List<string> l = new List<string>();
try
{
foreach (var line in File.ReadAllLines(fileToSearch))
{
if (line.Contains(textToSearch))
l.Add(line);
}
}
catch(Exception err)
{
string fff = err.ToString();
}
return l;
}
The first problem is when getting the number of directories:
private void btnProcess_Click(object sender, EventArgs e)
{
btnProcess.Enabled = false;
btnDirectory.Enabled = false;
btnCancel.Visible = true;
btnCancel.Enabled = true;
btnCancel.Text = "Cancel";
MyProgressBar.Visible = true;
_FileProcessingWorker = new BackgroundWorker();
_FileProcessingWorker.WorkerReportsProgress = true;
_FileProcessingWorker.WorkerSupportsCancellation = true;
_FileProcessingWorker.DoWork += new DoWorkEventHandler(_FileProcessingWorker_DoWork);
_FileProcessingWorker.ProgressChanged += new ProgressChangedEventHandler(_FileProcessingWorker_ProgressChanged);
_FileProcessingWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_FileProcessingWorker_RunWorkerCompleted);
string BasePath = lblDirectoryName.Text;
DirectoryInfo MyDirectory = new DirectoryInfo(BasePath);
DirectoryInfo[] MySubDirectories = MyDirectory.GetDirectories();
int SubDirectoryCount = MySubDirectories.GetLength(0);
MyProgressBar.Minimum = 0;
MyProgressBar.Step = 1;
MyProgressBar.Maximum = SubDirectoryCount;
MyProgressBar.Value = MyProgressBar.Minimum;
_LastCounter = 0;
_FileProcessingWorker.RunWorkerAsync(MySubDirectories);
}
In the click button i'm getting the sub directories.
But there are two problems.
In the dowork event when i put a break point on this line:
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
I see that it contain 409 directories. But when i report the number of directories to the label4 in the dowork event
CurrentStatus[3] = i.ToString();
In the progresschanged event
label4.Text = StatusMsg[3].ToString();
I see in the end on label4 408 directories. And in D:(in this case i'm working on my D:\ directory) when i select all the directories in windows explorer make right click and properties i see only 405 directories. So what is the real number of directories ? What and how number of directories should i display in label4 ?
The second problem is when i report the number of files in dowork event:
CurrentStatus[4] = totalFiles.ToString();
And in progresschanged event show it on label2:
label2.Text = StatusMsg[4].ToString();
The problem is that the totalFiles value is changing all the time once it's 2 then it's 768 then it's 66 then 8987 but what i want to do is somehow to sum in real time the values in totalFiles so in label2 i will see first time for example: 2 then 770 then (770+66) so i will see in label2 816....to see always the sum of all the values so far.
The last problem is in the progresschanged event this loop:
for (int i = 0; i < l.Count; i++)
{ ListViewCostumControl.lvnf.Items.Add("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
w.WriteLine("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
}
It might be logic somehow to take out and make this loop at this time in the program in another backgroundworker like backgroundworker2 dowork event ? If so how to do it ? The problem is when the loop have many items to add to the listView it make the program to hang until the loop finish.
Each time you execute
CurrentStatus[4] = totalFiles.ToString();
You are resetting the status value to the count of files in the current processing directory. This is why the number keeps bouncing around. Instead I would suggest:
int thisDirFiles;
thisDirFiles = l.Count;
totalFiles += thisDirFiles;
CurrentStatus[4] = totalFiles.ToString();
Now when you report progress, CurrentStatus[4] will have the running total.
For your second question, it looks to me you are trying to do too much when you are reporting progress. Manipulating ListViews can be costly, and you are probably spending more time updating the ListView than you are processing the directories, so your machine seems to freeze.

Zip the folder is not working first time C# and DotNetZip

I have a DotNetZip code for zipping the folder. It doesnt zip the file for the first time after cleaning the solution. After that it works fine. Can anybody know the issue why its happening??
Button Click Event Code
private void button3_Click(object sender, EventArgs e)
{
try
{
copy_stuff(textBox1.Text, textBox2.Text, textBox3.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Method that gets called from Button Click
private void copy_stuff(string srcFolder, string destFolder, string Backup)
{
using (ZipFile zip = new ZipFile())
{
zip.AddProgress += AddProgressHandler;
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
zip.SaveProgress += SaveProgress;
zip.StatusMessageTextWriter = System.Console.Out;
zip.AddDirectory(destFolder);
zip.Save(Backup + "\\VibrantBackup" + DateTime.Now.ToString("yyyyMMdd hh.mm.ss") + ".zip");
label1.Text = "Compression completed.";
}
}
Add & Save Handlers for Progress
int _numEntriesToAdd = 0;
int _numEntriesAdded = 0;
void AddProgressHandler(object sender, AddProgressEventArgs e)
{
switch (e.EventType)
{
case ZipProgressEventType.Adding_Started:
_numEntriesToAdd = 0;
_numEntriesAdded = 0;
label1.Text = "Adding files to the zip...";
label1.Update();
Application.DoEvents();
break;
case ZipProgressEventType.Adding_AfterAddEntry:
_numEntriesAdded++;
label1.Text = String.Format("Adding file: {0} :: {2}",
_numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName);
label1.Update();
Application.DoEvents();
break;
case ZipProgressEventType.Adding_Completed:
label1.Text = "Added all files";
label1.Update();
Application.DoEvents();
break;
}
}
public void SaveProgress(object sender, SaveProgressEventArgs e)
{
if (e.EventType == ZipProgressEventType.Saving_Started)
{
label1.Text = "Begin Saving: " + e.ArchiveName;
label1.Update();
Application.DoEvents();
}
else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
{
label1.Text = "Processing : " + e.CurrentEntry.FileName;
label1.Update();
label3.Text = "Files Processed: (" + (e.EntriesSaved + 1) + "/" + e.EntriesTotal + ")";
label3.Update();
Application.DoEvents();
progressBar3.Maximum = e.EntriesTotal;
progressBar3.Value = e.EntriesSaved + 1;
}
else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead)
{
//progressBar2.Value = (int)((e.BytesTransferred * 100) / e.TotalBytesToTransfer);
//label3.Text = "Writing: " + e.CurrentEntry.FileName + " (" + (e.EntriesSaved + 1) + "/" + e.EntriesTotal + ")";
label1.Update();
Application.DoEvents();
}
}

Categories

Resources