BackgroundWorker & Progressbar Issues c# Visual Studio 2010 - c#

Im trying to get my head around backgroundworker and the progressbar, so far i have got it to work but not exactly how i want it to work. Basically i am sorting/renaming folders and copying them to a different location, this works and the code is self explanatory, the output folders generated are as expected. However for each folder i intend to search through i have to right click it to get the number of files and then in the code i have to set the progressBar1.Maximum to that value in order for it to show the coreect progression of the progress bar. How is it possible to get this to set the number of files automatically since it goes through each folder anyway? Some folders have thousands of files and others have millions. beyond this i want to add a label so that it displays the name of the file it is processing along with the progressbar updates.
namespace Data_Sorter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnSelect_Click(object sender, EventArgs e)
{
folderBrowserDialog1.ShowDialog();
tbFilePath.Text = folderBrowserDialog1.SelectedPath.ToString();
}
private void btnSort_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int totalFiles = 0;
foreach (var file in Directory.GetFiles(tbFilePath.Text, "*.txt", SearchOption.AllDirectories))
{
backgroundWorker1.ReportProgress(totalFiles);
string fullFilename = file.ToString();
string[] pathParts = fullFilename.Split('\\');
string date = pathParts[6];
string fileName = pathParts[7];
string[] partName = fileName.Split('_');
string point = partName[3];
Directory.CreateDirectory("Data Sorted Logs\\" + point + "\\" + date + "\\");
if (Directory.Exists(("Data Sorted Logs\\" + point + "\\" + date + "\\")))
{
string destPath = (point + "\\" + date + "\\");
File.Copy(fullFilename, "C:\\Documents and Settings\\PC\\Desktop\\Sorter\\Data Sorter\\bin\\Debug\\Data Sorted Logs\\" + destPath + fileName); }
else
{
MessageBox.Show("destination folder not found " + date + point);
}
totalFiles++;
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Maximum = 6777; // set this value at the maximum number of files you want to sort //
progressBar1.Value = e.ProgressPercentage;
}
}

You can find out the file number simply reading the GetFiles length.
You can pass the relative percentage using the expression: (i * 100) / totalFiles, in this way it's not necessary to set the Maximum value for the progress.
You can also report the filename to the progressbar passing it as the UserState in the progressChanged event.
Try the code below:
namespace Data_Sorter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnSelect_Click(object sender, EventArgs e)
{
folderBrowserDialog1.ShowDialog();
tbFilePath.Text = folderBrowserDialog1.SelectedPath.ToString();
}
private void btnSort_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int totalFiles = 0;
string[] files = Directory.GetFiles(tbFilePath.Text, "*.txt", SearchOption.AllDirectories);
totalFiles = files.Length;
int i = 0;
foreach (var file in files)
{
backgroundWorker1.ReportProgress((i * 100) / totalFiles, file);
i++
string fullFilename = file.ToString();
string[] pathParts = fullFilename.Split('\\');
string date = pathParts[6];
string fileName = pathParts[7];
string[] partName = fileName.Split('_');
string point = partName[3];
Directory.CreateDirectory("Data Sorted Logs\\" + point + "\\" + date + "\\");
if (Directory.Exists(("Data Sorted Logs\\" + point + "\\" + date + "\\")))
{
string destPath = (point + "\\" + date + "\\");
File.Copy(fullFilename, "C:\\Documents and Settings\\PC\\Desktop\\Sorter\\Data Sorter\\bin\\Debug\\Data Sorted Logs\\" + destPath + fileName); }
else
{
MessageBox.Show("destination folder not found " + date + point);
}
totalFiles++;
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
progressBar1.Text = e.UserState.ToString();//or yourNewLabel.Text = e.UserState.ToString();
}
}

Move the call to GetFiles up so you can get the length of the array it returns:
string[] files = Directory.GetFiles(tbFilePath.Text, "*.txt",
SearchOption.AllDirectories));
// Note - you won't be able to set this UI property from DoWork
// because of cross-thread issues:
// progressbar1.Maximum = files.Length;
int fileCount = files.Length;
foreach (var file in files ...

Related

Changing the Path of a file from a User's Input on a form in C#

My user can create a file name that goes to a specific directory path(Textbox3) and they can change the directory path(TextBox4), I am having trouble reading Textbox4 which is the changing the path textbox.
It reads textbox3 just fine and does everything i need it to do if there is a filename in the textbox but when i put something in textbox4 it is not reading it.
private void textBox3_TextChanged(object sender, EventArgs e) //reads fine, file goes to C:\\Temp
{
string textBoxContents = textBox3.Text;
}
private void textBox4_TextChanged(object sender, EventArgs e)//this is not required, this is only if they want to change where the file is going Ex:(D:\\Test
{
string textBoxContents = textBox4.Text;
}
private void button1_Click(object sender, EventArgs e)
{
string Filename = textBox3.Text.Substring(0) + ".txt";
string Filepath = textBox4.Text.Substring(0) + ".txt";
var files = Directory.GetFiles(#"C:\\Temp").Length;
string path2 = Path.GetFullPath("C:\\Temp");
string docPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string var = Path.Combine(docPath, path2);
string var1 = Path.Combine(var, Filename);
using (StreamWriter objWriter = new StreamWriter(var1))
{
int numpins = int.Parse(textBox1.Text);
string basepin = textBox2.Text;
int pinlength = basepin.Length;
string formatspecifier = "{0:d" + pinlength.ToString() + "}" + "{1}";
long pinnumber = long.Parse(basepin);
string dig = textBox2.Text;
string result = GetCheckDigit(dig);
objWriter.WriteLine($"These are the Bin ranges");
objWriter.WriteLine();
for (int d = 0; d < numpins; d++)
{
if (String.IsNullOrEmpty(dig))
{
throw new Exception("null value not allowed");
}
else
{
dig = pinnumber.ToString();
result = GetCheckDigit(dig);
}
basepin = string.Format(formatspecifier, pinnumber, result);
objWriter.WriteLine(basepin);
pinnumber++;
}
objWriter.Close();
MessageBox.Show("File has been created");
}
}

I have a query about checked list boxes in c#

I have set up a program that so far can browse for the location of a file that possesses data in a text file holding the locations of other files which then shows me if they exist, are missing or are a duplicate inside listboxes. The next step is to enable the user to select files in the checked list boxes and being given the option to either move or copy. I have already made buttons which allow this but I want to be able to use them for the checked boxes I the list boxes.(p.s) please ignore any comments I have made in the code they are just previous attempts of doing other things in the code.
My code so far:
namespace File_existence
{
public partial class fileForm : Form
{
private string _filelistlocation;
public fileForm()
{
InitializeComponent();
}
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
public void fileForm_Load(object sender, System.EventArgs e)
{
_filelistlocation = textBox1.Text;
}
private void button1_Click(object sender, System.EventArgs e)
{
//GetDuplicates();
checkedListBox1.Items.Clear();
listBox2.Items.Clear();
ReadFromList();
}
private void GetDuplicates()
{
DirectoryInfo directoryToCheck = new DirectoryInfo(#"C:\\temp");
FileInfo[] files = directoryToCheck.GetFiles("*.*", SearchOption.AllDirectories);
var duplicates = files.GroupBy(x => x.Name)
.Where(group => group.Count() > 1)
.Select(group => group.Key);
if (duplicates.Count() > 0)
{
MessageBox.Show("The file exists");
FileStream s2 = new FileStream(_filelistlocation, FileMode.Open, FileAccess.Read, FileShare.Read);
// open _filelistlocation
// foreach line in _filelistlocation
// concatenate pat hand filename
//
}
}
public void ReadFromList()
{
int lineCounter = 0;
int badlineCounter = 0;
using (StreamReader sr = new StreamReader(_filelistlocation))
{
String line;
while ((line = sr.ReadLine()) != null)
{
string[] values = line.Split('\t');
if (values.Length == 2)
{
string fullpath = string.Concat(values[1], "\\", values[0]);
if (File.Exists(fullpath))
checkedListBox1.Items.Add(fullpath);
else
listBox2.Items.Add(fullpath);
++lineCounter;
}
else
++badlineCounter;
//Console.WriteLine(line);
}
}
}
//StreamReader files= new StreamReader(File)();
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
}
private void button2_Click(object sender, System.EventArgs e)
{
FolderBrowserDialog folderBrowserDlg = new FolderBrowserDialog();
folderBrowserDlg.ShowNewFolderButton = true;
DialogResult dlgResult = folderBrowserDlg.ShowDialog();
if (dlgResult.Equals(DialogResult.OK))
{
textBox1.Text = folderBrowserDlg.SelectedPath;
Environment.SpecialFolder rootFolder = folderBrowserDlg.RootFolder;
}
try
{
string fileName = "filetest1.txt";
string sourcePath = #"C:\Temp\Trade files\removed";
string targetPath = #"C:\Temp\Trade files\queued";
string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
string destFile = System.IO.Path.Combine(targetPath,fileName);
System.IO.File.Copy(sourceFile, destFile, true);
}
catch (IOException exc)
{
MessageBox.Show(exc.Message);
}
}
private void button3_Click(object sender, System.EventArgs e)
{
try
{
string sourceFile = #"C:\Temp\Trade Files\queued\filetest1.txt";
string destinationFile = #"C:\Temp\Trade Files\processed\filetest1.txt";
System.IO.File.Move(sourceFile, destinationFile);
}
catch(IOException ex){
MessageBox.Show(ex.Message);//"File not found"
}
}
private void button4_Click(object sender, System.EventArgs e)
{
OpenFileDialog fileBrowserDlg = new OpenFileDialog();
//folderBrowserDlg.ShowNewFolderButton = true;
//folderBrowserDlg.SelectedPath = _filelistlocation;
fileBrowserDlg.FileName = textBox1.Text;
DialogResult dlgResult = fileBrowserDlg.ShowDialog();
if (dlgResult.Equals(DialogResult.OK))
{
textBox1.Text = fileBrowserDlg.FileName;
File_existence.Properties.Settings.Default.Save();
// Environment.SpecialFolder rootFolder = folderBrowserDlg.RootFolder;
}
}
private void button5_Click(object sender, System.EventArgs e)
{
if (!textBox1.Text.Equals(String.Empty))
{
if (System.IO.Directory.GetFiles(textBox1.Text).Length > 0)
{
foreach (string file in System.IO.Directory.GetFiles(textBox1.Text))
{
checkedListBox1.Items.Add(file);
}
}
else
{
checkedListBox1.Items.Add(String.Format("No file found: {0}", textBox1.Text));
}
}
}
}
}
The task I need to do is that the files that appear in the checked list box need to usually be moved or copied to another directory. That is fine as I can already do that with what I have coded, but what it does is it will move or copy all of the files in the checked list box. What I want to do is enable the user to only be able to select which files they what to move or copy through checking the checked list box so that only those files will be moved or copied.
EDIT: Could it be checkedListBox.checked items?

Using checkboxlist to update registry?

I have a check list box that has 5 directories that my program will call later. I want the user to be able to check what directories they want to use with a checklistbox. So far they can chose each item they want and it will be added but i want unchecked boxs to be removed from the registry
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "";
foreach (object checkbox in checkedListBox1.CheckedItems)
{
textBox1.AppendText("Item is marked: " + checkbox.ToString() + "\n");
RegBUP.SetValue(checkbox);
}
}
And so people have a more general idea of what I am doing:
catchpath() returns the path from a directory, so if it gets desktop it returns the path to the desktop.
public static void SetValue(object title)
{
RegistryKey directs = regKey.OpenSubKey("Path to registry", true);
directs.SetValue(title.ToString(), catchpath(title), RegistryValueKind.String);
directs.Close();
}
// you can try this
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "";
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
if (checkedListBox1.GetItemChecked(i) == true)
{
textBox1.AppendText("Item is marked: " +checkedListBox1.Items[i].ToString()+ "\n");
RegBUP.SetValue(checkedListBox1.Items[i]);
}
else
{
RegBUP.DeleteValue(checkedListBox1.Items[i]);
}
}
}

Flickering image after loading in winforms at timer tick event

My question is the following:
I have a timer and each 1 ms i want to load an image and display it in a picture box in win forms
The first images work very fine however from some point the images start loading hard.
Can you please tell me how to solve this problem?
Regards and thank you for your time :)
private string path = "";
private int index = 0;
private void fileSourceToolStripMenuItem_Click(object sender, EventArgs e)
{
if (ofd.ShowDialog() == DialogResult.OK)
{
string fullPath = ofd.FileName;
string fileName = ofd.SafeFileName;
path = fullPath.Replace(fileName, "");
MessageBox.Show("Path for file source has been selected");
}
}
private const string IMAGENAME = "TestImage";
Bitmap b;
private void timer_Tick(object sender, EventArgs e)
{
try
{
string currentImage = IMAGENAME + index.ToString() + ".bmp";
index++;
b = new Bitmap(path + "\\" + currentImage);
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Image = b;
}
catch { };
}
private void button1_Click(object sender, EventArgs e)
{
timer.Start();
}
private void button2_Click(object sender, EventArgs e)
{
timer.Stop();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
string currentImage = IMAGENAME + index.ToString() + ".bmp";
index += 1;
Bitmap b = new Bitmap(path + "\\" + currentImage);
pb.Image = b;
}
catch { };
}
private void button4_Click(object sender, EventArgs e)
{
try
{
index -= 1;
string currentImage = IMAGENAME + index.ToString() + ".bmp";
Bitmap b = new Bitmap(path + "\\" + currentImage);
pb.Image = b;
}
catch { };
}
Play with DoubleBuffered property first.
GDI+ is very slow and even when using double buffering then it's still slow.
I would suggest you to find an alternative as there isn't really a way to fix the "flickering".
However there is one thing, the way you're actually loading the images in the tick handle is pretty cpu consuming.
I would suggest you load all the required image's bytes into a collection of some sort, ex. an array.
Then simply create the bitmap from the image bytes.
Besides you're not even disposing the current image, which you should before allocating new memory for the next image.

For each listbox item in variable

somehow i seem to be blind this morning ;)
i have the following code[1] which does read
the object collection out of an ListBox.
with the string b i can "retrieve" the strings
in b there are filenames and directory paths stored
that i want to backup with xcopy code [2].
Code:
private void btnBenutz_Click(object sender, EventArgs e)
{
lblAusgabe2.Text = "";
ListBox.ObjectCollection a = listBox1.Items;
foreach (string x in a)
{
b = x;
lblAusgabe2.Text += "\n" + b;
}
}
More code:
Process.Start("XCOPY.EXE", "/E /I /Y" + b + pfadauswahl + "\\Backup\\" + dt.ToString("yyyy-MM-dd") + "\\UserData\\");
how can i use b as an array which i probably have to ? otherwise only the first item will always been read out? Also the process start i have to use outside of the btnBenutz... so some variable has to be initialized in the public partial class Form2 : Form
Define b as List<string>. You also use a better name like fileNameList:
private List<string> fileNameList; // a class field, not a local variable
Then add the file names to the list:
private void btnBenutz_Click(object sender, EventArgs e)
{
lblAusgabe2.Text = "";
ListBox.ObjectCollection a = listBox1.Items;
foreach (string x in a)
{
fileNames.Add(x);
lblAusgabe2.Text += Environment.NewLine + x; // Why are you doing this?
}
}
Then in another place, run the xopy command for each file:
foreach(string fileName in fileNameList)
{
Process.Start("XCOPY.EXE", "/E /I /Y " + fileName + pfadauswahl + "\\Backup\\" + dt.ToString("yyyy-MM-dd") + "\\UserData\\");
}
if that's what you are trying to achieve!
private void btnBenutz_Click(object sender, EventArgs e)
{
var sb = new StringBuilder();
foreach (string x in listBox1.Items)
{
sb.Append("\n" + x);
}
// then use sb.ToString() somewhere...
}
As you commented you want to call it from other places also like another button click then
Do something like this :
1) Declare list of string at class level
List<string> fileNameList ;
2) Create a function with some meaningfull name let's say StartXcopy like below
public void StartXcopy()
{
ListBox.ObjectCollection a = listBox1.Items;
fileNameList = new List<string>();
foreach (string x in a)
{
fileNameList.Add(x);
lblAusgabe2.Text += "\n" + x;
}
foreach (string filename in fileNameList)
{
System.Diagnostics.Process.Start("XCOPY.EXE", "/E /I /Y" + filename + pfadauswahl + "\\Backup\\" + dt.ToString("yyyy-MM-dd") + "\\UserData\\");
}
}
3) Then call this function from where you want, like below in button click
private void btnBenutz_Click(object sender, EventArgs e)
{
lblAusgabe2.Text = "";
StartXcopy();
}
Note : Here i am assuming you are always iterating through listBox1 items.

Categories

Resources