I need to pass information from thread of scanning data to recording information thread(write to xml file).
It should looks something like this:
Application.Run() – complete
Scanning thread – complete
Writing to xlm thread – ???
UI update thread – I think I did it
And what i got now:
private void StartButtonClick(object sender, EventArgs e)
{
if (FolderPathTextBox.Text == String.Empty || !Directory.Exists(FolderPathTextBox.Text)) return;
{
var nodeDrive = new TreeNode(FolderPathTextBox.Text);
FolderCatalogTreeView.Nodes.Add(nodeDrive);
nodeDrive.Expand();
var t1 = new Thread(() => AddDirectories(nodeDrive));
t1.Start();
}
}
private void AddDirectories(TreeNode node)
{
string strPath = node.FullPath;
var dirInfo = new DirectoryInfo(strPath);
DirectoryInfo[] arrayDirInfo;
FileInfo[] arrayFileInfo;
try
{
arrayDirInfo = dirInfo.GetDirectories();
arrayFileInfo = dirInfo.GetFiles();
}
catch
{
return;
}
//Write data to xml file
foreach (FileInfo fileInfo in arrayFileInfo)
{
WriteXmlFolders(null, fileInfo);
}
foreach (DirectoryInfo directoryInfo in arrayDirInfo)
{
WriteXmlFolders(directoryInfo, null);
}
foreach (TreeNode nodeFil in arrayFileInfo.Select(file => new TreeNode(file.Name)))
{
FolderCatalogTreeView.Invoke(new ThreadStart(delegate { node.Nodes.Add(nodeFil); }));
}
foreach (TreeNode nodeDir in arrayDirInfo.Select(dir => new TreeNode(dir.Name)))
{
FolderCatalogTreeView.Invoke(new ThreadStart(delegate
{node.Nodes.Add(nodeDir);
}));
StatusLabel.BeginInvoke(new MethodInvoker(delegate
{
//UI update...some code here
}));
AddDirectories(nodeDir);
}
}
private void WriteXmlFolders(DirectoryInfo dir, FileInfo file)
{//writing information into the file...some code here}
How to pass data from AddDirectories(recursive method) thread to WriteXmlFolders thread?
Here is a generic mechanism how one thread generates data that another thread consumes. No matter what approach (read: ready made classes) you would use the internal principle stays the same. The main players are (note that there are many locking classes available in
System.Threadingnamespace that could be used but these are the most appropriate for this scenario:AutoResetEvent– this allows a thread to go into sleep mode (without consuming resources) until another thread will wake it up. The ‘auto’ part means that once the thread wakes up, the class is reset so the nextWait()call will again put it in sleep, without the need to reset anything.ReaderWriterLockorReaderWriterLockSlim(recommended to use the second if you are using .NET 4) – this allows just one thread to lock for writing data but multiple threads can read the data. In this particular case there is only one reading thread but the approach would not be different if there were many.In .NET 4 it is possible to avoid using
ReadWriteLockand use one of the concurrency-safe collections such asConcurrentQueuewhich will internally make sure that reading/writing is thread safe. TheAutoResetEventis still needed though..NET 4 provides a mechanism that could be used to avoid the need of even
AutoResetEvent–BlockingCollection– this class provides methods for a thread to sleep until data is available. MSDN page contains example code on how to use it.