Reputation: 3511
I've the following scenario, I've to copy multiple (about 10,50,200,...) files. I do that syncronously one after another. This is my code snippet for that.
static void Main(string[] args)
{
string path = @"";
FileSystemWatcher listener = new FileSystemWatcher(path);
listener.Created += new FileSystemEventHandler(listener_Created);
listener.EnableRaisingEvents = true;
while (Console.ReadLine() != "exit") ;
}
public static void listener_Created(object sender, FileSystemEventArgs e)
{
while (!IsFileReady(e.FullPath)) ;
File.Copy(e.FullPath, @"D:\levani\FolderListenerTest\CopiedFilesFolder\" + e.Name);
}
So when files are created in some folder and it's ready to use I copy that file one after another, but I need to start copying as soon as any file is ready to use. So I think I should use Threads. So.. How to implement parallel copying?
@Chris
Check if file is ready
public static bool IsFileReady(String sFilename)
{
// If the file can be opened for exclusive access it means that the file
// is no longer locked by another process.
try
{
using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
if (inputStream.Length > 0)
{
return true;
}
else
{
return false;
}
}
}
catch (Exception)
{
return false;
}
}
Upvotes: 5
Views: 5796
Reputation: 948
You could possibly have one Thread
which does all the processing i.e.
Queue files = new Queue();
static void Main(string[] args)
{
string path = @"";
FileSystemWatcher listener = new FileSystemWatcher(path);
Thread t = new Thread(new ThreadStart(ProcessFiles));
t.Start();
listener.Created += new FileSystemEventHandler(listener_Created);
listener.EnableRaisingEvents = true;
while (Console.ReadLine() != "exit") ;
}
public static void listener_Created(object sender, FileSystemEventArgs e)
{
files.Enqueue(e.FullPath);
}
void ProcessFiles()
{
while(true)
{
if(files.Count > 0)
{
String file = files.Dequeue();
while (!IsFileReady(file)) ;
File.Copy(file, @"D:\levani\FolderListenerTest\CopiedFilesFolder\" + file);
}
}
}
And in your listener
event add the file name to a queue.
Then in your Thread
you can grab the file name from the queue and do your processing from there.
Upvotes: 2
Reputation: 19956
Now only that (what @Tudor says), but copying files in parallel will create mess out of your hard drive, due to fragmenting. In my app, I use queued copying of 200 simultaneously previously generated files, just to put them on the hard drive in 'linear' fashion.
You can read some more on the subject here.
Upvotes: 2
Reputation: 62439
Doing parallel I/O from a mechanical disk is a bad idea and will only slow things down, as the mechanical head needs to spin every time to seek the next read location (a very slow process) and will then be bounced around as each thread gets its turn to run.
Stick to the sequential approach and read the files in a single thread.
Upvotes: 12