I have a ListBox which I put some files, if the file is not AVI I automatically converts it but I want when the files converting message will write on a label that the files are now converted to another format, what happens to me now is only when the program has finished converting them its update the label and not in the process
after all the fixes:
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
btnPlay.IsEnabled = false;
Stream checkStream = null;
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
openFileDialog.Multiselect = true;
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "All files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.Title = "Please Select Source File";
if ((bool)openFileDialog.ShowDialog())
{
if ((checkStream = openFileDialog.OpenFile()) != null)
{
foreach (string file in openFileDialog.FileNames)
{
try
{
FileInfo fileInfo = new FileInfo(file);
listBoxFiles.Items.Add(file);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
for (int i = 0; i < listBoxFiles.Items.Count; i++)
{
string path = (string)listBoxFiles.Items[i];
FileInfo fileInfo = new FileInfo(path);
if (fileInfo.Extension != ".AVI")
{
listToRemove.Add(path);
}
}
(new System.Threading.Thread(ProcessAviFiles)).Start();
foreach (string file in listToRemove) //remove all non .AVI files from listbox
{
listBoxFiles.Items.Remove(file);
}
}
}
else
{
}
if (listBoxFiles.Items.Count != 0)
{
btnClear.IsEnabled = true;
btnPlay.IsEnabled = true;
}
listToRemove.RemoveRange(0, listToRemove.Count);
}
function:
public void ProcessAviFiles()
{
if (listToRemove.Count == 0)
{
return;
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() => { lblStatus2.Content = "Convert file to .AVI..."; }));
foreach (String file in listToRemove)
{
FileInfo fileInfo = new FileInfo(file);
editpcap = new EditCap(fileInfo);
String newFileName = editpcap._newFileName;
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
{
listBoxFiles.Items.Add(editpcap._newFileName);
}));
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
() =>
{
lblStatus2.Content = "Select adapter and packet file, Click play button to start.";
btnClear.IsEnabled = true;
}));
}
The label is not updating because the main UI thread is busy doing other things.
Looking to your code, it seems that you are running the AVI file conversion business inside your main UI thread. You should run this time consuming task in a separate thread to make sure your UI stays responsive.
Below is a fix to your problem, replace your foreach (String file in listToRemove){} by:
Action aviConversion = new Action(() => {
if(listToRemove.Count == 0) return; // nothing to do
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "Convert file to .AVI...";});
);
foreach (String file in listToRemove){
FileInfo fileInfo = new FileInfo(file);
editpcap = new (classes who convert the files)(fileInfo);
String newFileName = editpcap._newFileName;
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => {
listBoxFiles.Items.Add(newFileName);
}));
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "AVI file conversion finished...";});
});
// Run this action in a separate thread...
Task.Factory.StartNew(action, "beta");
EDIT Using Thread instead of Task (OP can't use Task)
private void ProcessAviFiles(){
if(listToRemove.Count == 0) return; // nothing to do
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "Convert file to .AVI...";});
);
foreach (String file in listToRemove){
FileInfo fileInfo = new FileInfo(file);
editpcap = new (classes who convert the files)(fileInfo);
String newFileName = editpcap._newFileName;
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => {
listBoxFiles.Items.Add(newFileName);
}));
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "AVI file conversion finished...";});
}
replace your foreach (String file in listToRemove){} by:
(new System.Threading.Thread(ProcessAviFiles)).Start();
Use BackgroundWorker for the main task and dispatcher for UI updates.
backgroundWorker1.DoWork += worker_DoWork;
backgroundWorker1.RunWorkerCompleted += worker_RunWorkerCompleted;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
Related
This question already has answers here:
How to limit the amount of concurrent async I/O operations?
(11 answers)
Closed 1 year ago.
I copy files in a Zip archive (3td part library to get the progress) with a BackgroundWorker so I not block the UI and I can upgrade the ProgressBar or cancel the copy.
This is the code of BackgroundWorker, source, target and name are general variable:
private void _backgroundWorkerB1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
//Check if the source directory exist
if (Directory.Exists(source) == false)
{
e.Result = "NotExist";
return;
}
//If the target not exist I will create it
if (Directory.Exists(target) == false)
{
Directory.CreateDirectory(target);
}
string filename = target + "\\" +
DateTime.Now.ToString("yyyy'-'MM'-'dd'_'HH'_'mm'_'ss") +
"-" + name + ".zip";
// 3td part library
ArchivioB1.FileName = filename;
ArchivioB1.OpenArchive(System.IO.FileMode.Create);
ArchivioB1.OnOverallProgress += new BaseArchiver
.OnOverallProgressDelegate(ArchivioB1_OnOverallProgress);
// Source directory
ArchivioB1.BaseDir = source;
// Copy all files
ArchivioB1.AddFiles("*.*");
// Close
ArchivioB1.CloseArchive();
}
catch (Exception ex)
{
e.Result = "Error";
return;
}
}
I need to modify the code to make it in parallel from a DataGrid. I will have a DataGrid on the first column the name of the file, on the second a progress bar, on third the State and on fourth the destination of file.
The DataGrid can have an undefined rows and these rows can be more than cores of the CPU. How can I run the same function in parallel, and if the rows are more than the CPU cores, the system have to wait till one of it will be free and continue with the next copy?
I don't understand why the community have to close the question when isn't duplicate like they think, in any case if someone need to copy files in archive parallely with a progress
Hereafter final Edit with working code:
private async void btBackup_Click(object sender, RoutedEventArgs e)
{
btBackup.IsEnabled = false;
btCancel.IsEnabled = true;
var row_list1 = GetDataGridRows(dgwStation);
List<Task> tasks = new List<Task>();
ZipForge[] ZipList = new ZipForge[DataGridItemsList.Count];
tokenSource = new CancellationTokenSource();
foreach (DataGridRow single_row in row_list1)
{
int riga = single_row.GetIndex();
ZipList[riga] = new ZipForge();
tasks.Add(Task.Run(() => CopyTest(riga,ZipList[riga])));
}
await Task.WhenAll(tasks);
if (generalerror)
tbkStato.Text = "Completed with error";
else if (tbkStato.Text != "Cancelled")
tbkStato.Text = "Completed";
}
private void btCancel_Click(object sender, RoutedEventArgs e)
{
try
{
if (tokenSource != null) //se il token non รจ nullo, posso chiedere la cancellazione
{
//tbkStato.Text = "Cancelled";
tokenSource.Cancel();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public void CopyTest(int rowindex, ZipForge ArchivioB1)
{
string nome1 = "";
try
{
//Takes data from DatGridItemsList
string source = DataGridItemsList[rowindex].Source, target = DataGridItemsList[rowindex].Target, filename = DataGridItemsList[rowindex].FileName;
tbkStato.Dispatcher.Invoke(new Action(() => { tbkStato.Text = "Check source"; }));
if (Directory.Exists(source) == false)
{
DataGridItemsList[rowindex].State = "Not Exist";
dgwStation.Dispatcher.Invoke(new Action(() => { dgwStation.Items.Refresh(); }));
generalerror = true;
return;
}
tbkStato.Dispatcher.Invoke(new Action(() => { tbkStato.Text = "Check target"; }));
if (Directory.Exists(target) == false)
{
Directory.CreateDirectory(target);
}
DataGridItemsList[rowindex].State = "creating Zip";
dgwStation.Dispatcher.Invoke(new Action(() => { dgwStation.Items.Refresh(); }));
nome1 = target + "\\" + DateTime.Now.ToString("yyyy'-'MM'-'dd'_'HH'_'mm'_'ss") + "-" + filename + ".zip";
ArchivioB1.FileName = nome1;
ArchivioB1.OpenArchive(System.IO.FileMode.Create,FileAccess.Write);
ArchivioB1.Comment = rowindex.ToString();
ArchivioB1.OnOverallProgress += new BaseArchiver.OnOverallProgressDelegate(ArchivioB1_OnOverallProgress);
ArchivioB1.BaseDir = source;
// Copia tutti i file nell'archivio creato
ArchivioB1.AddFiles("*.*");
if (tokenSource.Token.IsCancellationRequested) //Interruzzione dell'utente
{
tokenSource.Token.ThrowIfCancellationRequested();
}
else
{
ArchivioB1.CloseArchive();
DataGridItemsList[rowindex].State = "Completed";
dgwStation.Dispatcher.Invoke(new Action(() => { dgwStation.Items.Refresh(); }));
}
}
catch (OperationCanceledException)
{
ArchivioB1.CloseArchive();
if (File.Exists(nome1))
File.Delete(nome1);
DataGridItemsList[rowindex].State = "Cancelled";
dgwStation.Dispatcher.Invoke(new Action(() => { dgwStation.Items.Refresh(); }));
tbkStato.Dispatcher.Invoke(new Action(() => { tbkStato.Text = "Cancelled"; }));
return;
}
catch (Exception ex)
{
ArchivioB1.CloseArchive();
if (File.Exists(nome1))
File.Delete(nome1);
DataGridItemsList[rowindex].State = ex.Message.ToString();
dgwStation.Dispatcher.Invoke(new Action(() => { dgwStation.Items.Refresh(); }));
generalerror = true;
return;
}
}
private void ArchivioB1_OnOverallProgress(object sender, double progress, TimeSpan timeElapsed, TimeSpan timeLeft, ProcessOperation operation, ProgressPhase progressPhase, ref bool cancel)
{
if (tokenSource.Token.IsCancellationRequested) //Interruzzione dell'utente
{
cancel = true;
//tokenSource.Token.ThrowIfCancellationRequested();
}
ZipForge Archivio = (ZipForge)sender;
int indice = Convert.ToInt32(Archivio.Comment);
DataGridItemsList[indice].Progress = Convert.ToInt32(progress);
dgwStation.Dispatcher.Invoke(new Action(() => { dgwStation.Items.Refresh(); }));
}
I would recommend using Tasks instead of Backgroundworkers.You can run as many Tasks as you wish in a simple mannner using Task.WhenAll...
If you want to execute tasks syncronously just omit await...
public async ExecuteMultipleTasksSimultaneously()
{
List<Task> tasks = new List<Task>()
{
Task.Factory.StartNew(() => ActionA()),
Task.Factory.StartNew(() => ActionB()),
Task.Factory.StartNew(() => ActionC())
};
//Execute all tasks "at the same time"...
await Task.WhenAll(tasks);
// or await Task.WhenAny(tasks);
// or await Task.WaitAll(tasks)
//or Task.WaitAny(tasks) depending on your execution needs
// Continue on this thread...
//Alternative to Task.Factory.StartNew(() => ActionA()) you could use
// Task.Run(()=> ActionA())
}
I hope this points the right direction. Best regards.
I tried to monitor the directory with FileWatcher. When several files changed I must insert added data of txt files into database. But it does not work after the second attempt. So, Windows shows such message: this file is used by another program. I think that it relates to the ReaderWriterLockSlim class which used in this code. Please, suppose your solutions. I am working with ASP.NET MVC, not Windows Forms App.
Here the code
public class MultiWatcher : IDisposable
{
private List<string> filePaths;
private ReaderWriterLockSlim rwlock;
private System.Timers.Timer processTimer;
private string watchedPath;
private FileSystemWatcher watcher;
private int readLinesCount = 0;
public MultiWatcher(string watchedPath)
{
filePaths = new List<string>();
rwlock = new ReaderWriterLockSlim();
this.watchedPath = watchedPath;
InitFileSystemWatcher();
}
private void InitFileSystemWatcher()
{
watcher = new FileSystemWatcher();
watcher.Filter = "*.txt";
watcher.Changed += new FileSystemEventHandler(Watcher_FileChanged);
watcher.Error += Watcher_Error;
watcher.Path = watchedPath;
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
private void Watcher_Error(object sender, ErrorEventArgs e)
{
// Watcher crashed. Re-init.
InitFileSystemWatcher();
}
private void Watcher_FileChanged(object sender, FileSystemEventArgs e)
{
try
{
rwlock.EnterWriteLock();
filePaths.Add(e.Name);
if (processTimer == null)
{
// First file, start timer.
processTimer = new System.Timers.Timer(1000);
processTimer.Elapsed += ProcessQueue;
processTimer.Start();
}
else
{
// Subsequent file, reset timer.
processTimer.Stop();
processTimer.Start();
}
}
finally
{
rwlock.ExitWriteLock();
}
}
private void ProcessQueue(object sender, ElapsedEventArgs args)
{
try
{
//Console.WriteLine("Processing queue, " + filePaths.Count + " files created:");
rwlock.EnterReadLock();
foreach (string filePath in filePaths)
{
RecordEntry(filePath); // try to insert txt file data into database
}
filePaths.Clear();
}
finally
{
if (processTimer != null)
{
processTimer.Stop();
processTimer.Dispose();
processTimer = null;
}
rwlock.ExitReadLock();
}
}
//insert txt file data into database
private void RecordEntry(string fileName)
{
if (fileName != null)
{
using (var fs = new FileStream(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName), FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (StreamReader reader = new StreamReader(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName)))
{
Data_access da = new Data_access();
readLinesCount = da.GetReadLinesCount(fileName);
int totalLinesCount = File.ReadAllLines(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName)).Length;
int newLinesCount = totalLinesCount - readLinesCount;
//var fileByLine = File.ReadLines(HostingEnvironment.MapPath("/Content/101_Sensors.txt")).Last();
var fileByLine = File.ReadLines(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName)).Skip(readLinesCount).Take(newLinesCount);
var each = fileByLine.Select(l => l.Split('_'));
string[] parsedFileContent = new string[fileByLine.Count()];
foreach (var item in fileByLine)
{
parsedFileContent = item.Split('_');
da.AddParams(parsedFileContent, totalLinesCount, fileName);
}
da.SetReadLinesCount(totalLinesCount, fileName);
}
}
//using (StreamReader reader = new StreamReader(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName)))
//{
// int totallinesCount = File.ReadAllLines(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName)).Length;
// int newLinesCount = totallinesCount - readLinesCount;
// //var fileByLine = File.ReadLines(HostingEnvironment.MapPath("/Content/101_Sensors.txt")).Last();
// var fileByLine = File.ReadLines(HostingEnvironment.MapPath("~/Content/Sensors/" + fileName)).Skip(readLinesCount).Take(newLinesCount);
// var each = fileByLine.Select(l => l.Split('_'));
// string[] parsedFileContent = new string[fileByLine.Count()];
// foreach (var item in fileByLine)
// {
// parsedFileContent = item.Split('_');
// da.AddParams(parsedFileContent, totallinesCount, fileName, readLinesCount);
// }
//}
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (rwlock != null)
{
rwlock.Dispose();
rwlock = null;
}
if (watcher != null)
{
watcher.EnableRaisingEvents = false;
watcher.Dispose();
watcher = null;
}
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
it's my first question I'm asking here, so please be gentle with me ;)
So I've actually got two WinForms in my C# application I'm writing at the moment (I'm quite new to C#).
This window has a button, which saves photos from an usb device you selected before in a list box to another folder.
After clicking on this button my main thread is of course busy with copying, so I decided to create another WinForm which contains my ProgressBar.
Foreach completed copy, I want to increment my ProgressBar accordingly.
So I count the number of copies I have to do and give it the progressbar as maximum. But my problem at the moment is, that I really don't know how to increment the ProgressBar without getting a Thread Unsafe Exception.
Here's my ProgressWindow code:
public partial class ProgressWindow : Form
{
BackgroundWorker updateProgressBarThread = new BackgroundWorker();
private Boolean _isThreadRunning = false;
public Boolean IsThreadRunning
{
get { return _isThreadRunning; }
set { _isThreadRunning = value; }
}
private int _progressbarLength;
public int ProgressbarLength
{
get { return _progressbarLength; }
set { _progressbarLength = value; }
}
private int progress = 1;
public ProgressWindow()
{
Show();
InitializeComponent();
}
private void StartUpdateThread(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Reports progress to the ProgressChangedEvent function. (Thread Safe)
}
private void FinishProgressThread(object sender, RunWorkerCompletedEventArgs e)
{
if (!_isThreadRunning)
{
MessageBox.Show("Erfolgreich kopiert");
Close();
}
}
private void ProgressChangedEvent(object sender, ProgressChangedEventArgs e)
{
this.copyProgressbar.Value = e.ProgressPercentage;
this.progressStatus.Text = e.ProgressPercentage.ToString();
}
public void CallUpdateThread()
{
updateProgressBarThread.WorkerReportsProgress = true;
updateProgressBarThread.DoWork += new DoWorkEventHandler(StartUpdateThread);
updateProgressBarThread.ProgressChanged += new ProgressChangedEventHandler(ProgressChangedEvent);
updateProgressBarThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FinishProgressThread);
updateProgressBarThread.RunWorkerAsync();
}
}
I want to increment my ProgressBar with 1 after each succesful copy.
How do I do this from my main thread?
This is the function which actually handles the copy process
private void SaveFile(System.IO.DirectoryInfo root)
{
try
{
IEnumerable<DirectoryInfo> directoriesNames = root.EnumerateDirectories();
// New instance of thread ProgressWindow.
ProgressWindow progress = new ProgressWindow();
progress.CallUpdateThread();
foreach (DirectoryInfo element in directoriesNames)
{
// Query all subdirectories and count everything with the in the configuration made settings.
if (!element.Attributes.ToString().Contains("System"))
{
// Now we insert the configuration we applied.
String fileExtension = null;
if (Properties.Settings.Default._configPhoto)
{
fileExtension = "*.jpg";
}
if (Properties.Settings.Default._configWordDocument)
{
fileExtension = "*.odt";
}
FileInfo[] jpgList = element.GetFiles(fileExtension, SearchOption.AllDirectories);
// set the size of the progress bar
progress.ProgressbarLength = jpgList.Count();
// Now we go through all our results and save them to our backup folder.
foreach (FileInfo tmp in jpgList)
{
string sourceFilePath = tmp.FullName;
string destFilePath = PATHTOBACKUP + "\\" + tmp.Name;
progress.IsThreadRunning = true;
try
{
System.IO.File.Copy(sourceFilePath, destFilePath, true);
}
catch (IOException ioe)
{
MessageBox.Show(ioe.Message);
}
}
}
}
// progress.IsThreadRunning = false;
}
catch (UnauthorizedAccessException e)
{
MessageBox.Show(e.Message);
}
}
It's pretty obvious that I have to do this after this function
System.IO.File.Copy(sourceFilePath, destFilePath, true);
But how do I report this to my ProgressWindow?
I really hope I explained it well enough, not sure if I'm missing something important.
Thanks in advance guys
Here is a compact example of the key components:
Clicking button starts new thread worker
Progress is done by file lengths, not by number of files
BeginInvoke used to update the progress bar (avoid cross Thread exception)
ProgressBar pb = new ProgressBar() { Minimum = 0, Maximum = 100 };
Button btn = new Button();
btn.Click += delegate {
Thread t = new Thread(() => {
DirectoryInfo dir = new DirectoryInfo("C:\\temp\\");
var files = dir.GetFiles("*.txt");
long totalLength = files.Sum(f => f.Length);
long length = 0;
foreach (var f in files) {
length += f.Length;
int percent = (int) Math.Round(100.0 * length / totalLength);
pb.BeginInvoke((Action) delegate {
pb.Value = percent;
});
File.Copy(f.FullName, "...");
}
});
t.IsBackground = true;
t.Start();
};
Eventhough i specify a different location the file gets saved in mydocuments. How to resolve this issue. Pls share your ideas if any.Here is the code.
if (externalButton.Checked == true)
{
// int i = 1;
saveFileDialog.Title = "Save the Proofer Report";
saveFileDialog.Filter = "Document Files (*.doc)|*.doc|Document Files (*.docx)|*.docx";
saveFileDialog.FilterIndex = 0;
saveFileDialog.InitialDirectory = "MyDocuments";
saveFileDialog.FileName = "Proofer Report -- " + Path.GetFileName((string)fileName) + ".doc";
//i.tostring()
saveFileDialog.DefaultExt = ".doc";
saveFileDialog.ShowHelp = true;
// saveFileDialog.ShowDialog();
var thread = new Thread(new ParameterizedThreadStart(param => { saveFileDialog.ShowDialog(); }));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
fname = saveFileDialog.FileName;
You are showing dialog assynchronously on new thread and code after starting the thread executes before dialog is shown (most of the time).
Either wait for thread completion or move saving to that thread after dialog is closed.
Why You Are Showing saveFileDialog in different thread?
if you show save dialog in diffrent thread fname = saveFileDialog.FileName; is always return null.dont use separate thread.or Call this event after thread start
saveFileDialog1.FileOk += new CancelEventHandler(saveFileDialog1_FileOk);
void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
{
string fname = null;
fname = saveFileDialog1.FileName;
}
Edited
Example
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
_SaveFileDialog.FileOk += new CancelEventHandler(_SaveFileDialog_FileOk);
}
string filename = null;
SaveFileDialog _SaveFileDialog = new SaveFileDialog();
private void savebtn_Click(object sender, EventArgs e)
{
_SaveFileDialog.Title = "Save the Proofer Report";
_SaveFileDialog.Filter = "Document Files (*.doc)|*.doc|Document Files (*.docx)|*.docx";
_SaveFileDialog.FilterIndex = 0;
_SaveFileDialog.InitialDirectory = "MyDocuments";
_SaveFileDialog.FileName = "Proofer Report -- .doc";
_SaveFileDialog.DefaultExt = ".doc";
_SaveFileDialog.ShowHelp = true;
var thread = new Thread(new ParameterizedThreadStart(param => { _SaveFileDialog.ShowDialog(); }));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
void _SaveFileDialog_FileOk(object sender, CancelEventArgs e)
{
filename = _SaveFileDialog.FileName;
}
}
I am use SafeFileEnumerator class to search for files inside folder root, this class return only files from location with permission so I am use it successfully.
When I try to fill my list in this way all works fine:
List<string> list = new List<string>();
list = SafeFileEnumerator.EnumerateFiles(folderBrowserDialog1.SelectedPath,
"*.*", SearchOption.AllDirectories).ToList();
But in this case my GUI freeze so I move it to new thread and in this case nothing happen and I wondered why:
private void btnAddDir_Click(object sender, EventArgs e)
{
List<string> list = new List<string>();
string fileToAdd = string.Empty;
List<string> filesList = new List<string>();
dialog = folderBrowserDialog1.ShowDialog();
tbAddDir.Text = folderBrowserDialog1.SelectedPath;
string pathToSearch = folderBrowserDialog1.SelectedPath;
if (dialog == DialogResult.OK)
{
toolStripStatusLabel.Text = "Search for pcap files...";
groupBoxRootDirectory.Enabled = false;
btnStart.Enabled = false;
ThreadStart starter = delegate
{
list = SafeFileEnumerator.EnumerateFiles(pathToSearch, "*.pcap", SearchOption.AllDirectories).ToList();
};
Thread t = new Thread(starter);
t.IsBackground = true;
t.Start();
if(list.Count != 0)
AddFilesToListBox(list);
}
}
SafeFileEnumerator class code:
public static class SafeFileEnumerator
{
public static IEnumerable<string> EnumerateDirectories(string parentDirectory, string searchPattern, SearchOption searchOpt)
{
try
{
var directories = Enumerable.Empty<string>();
if (searchOpt == SearchOption.AllDirectories)
{
directories = Directory.EnumerateDirectories(parentDirectory).SelectMany(x => EnumerateDirectories(x, searchPattern, searchOpt));
}
return directories.Concat(Directory.EnumerateDirectories(parentDirectory, searchPattern));
}
catch (UnauthorizedAccessException ex)
{
return Enumerable.Empty<string>();
}
}
public static IEnumerable<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOpt)
{
try
{
var dirFiles = Enumerable.Empty<string>();
if (searchOpt == SearchOption.AllDirectories)
{
dirFiles = Directory.EnumerateDirectories(path).SelectMany(x => EnumerateFiles(x, searchPattern, searchOpt));
}
return dirFiles.Concat(Directory.EnumerateFiles(path, searchPattern));
}
catch (UnauthorizedAccessException ex)
{
return Enumerable.Empty<string>();
}
}
}
after my list is full of files:
private void AddFilesToListBox(List<string> filesList)
{
string fileToAdd = string.Empty;
Editcap editcap = new Editcap();
Capinfos capinfos = new Capinfos();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork +=
(s1, e1) =>
{
foreach (string fileName in filesList)
{
FileInfo fileInfo = new FileInfo(fileName);
if (checkFileCreationDate(fileInfo))
{
if (editcap.isWiresharkFormat(fileInfo.FullName))
{
if (editcap.isLibpcapFormat(fileInfo.FullName))
{
addFileToListBox(fileInfo.FullName, capinfos.getFileDuration(fileInfo.FullName));
}
else if (!editcap.isLibpcapFormat(fileInfo.FullName))
{
fileToAdd = editcap.getNewFileName(fileInfo.FullName);
if (new FileInfo(fileToAdd).Exists && !fileInfo.Exists)
{
addFileToListBox(fileToAdd, capinfos.getFileDuration(fileInfo.FullName));
}
}
}
}
//this.Invoke((MethodInvoker)delegate { lvFiles.Items[lvFiles.Items.Count - 1].Selected = true; });
toolStripStatusLabel.Text = string.Format("{0} files were added", lvFiles.Items.Count);
}
//this.Invoke((MethodInvoker)delegate { lvFiles.Items[lvFiles.Items.Count - 1].Selected = true; });
};
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
(s1, e1) =>
{
groupBoxRootDirectory.Enabled = true;
btnClear.Enabled = true;
if (lvFiles.Items.Count != 0)
btnStart.Enabled = true;
toolStripStatusLabel.Text = string.Format("{0} files were added", lvFiles.Items.Count);
if (tbAddDir.Text != "")
{
listener = new FileListener();
listener.startListener(tbAddDir.Text);
listener._newFileEventHandler += listener_newFileEventHandler;
}
});
backgroundWorker.RunWorkerAsync();
}
after t.start() i am call AddFilesToListBox(list);
You did not implemented an asynchronous pattern.
After t.Start(); is called, the thread did not finished its work yet, so your list was still empty at the time you called AddFilesToListBox. Do implement an async pattern and call AddFilesToListBox once the thread finished its job.