G
Guest
Please see the code below as I am trying to use multithreading for copying
files to a new location in a way that improves performance of the client
windows application.
The problem occurs when 2 or more threads are created, the ImportOneFile
method attempts to add a previously added file. If I allow 4 maximum threads
and process 4 files, the last file is attempted 4 times and none of the other
files are added to the destination. If I reduce maximum threads to 2, the
second file is attempted twice, the first one is forgotten and other files
are added to the destination.
Anyone have any idea why the values passed to ImportOneFile are sometimes
"forgotten"? I thought the lock statement would protect against this.
Thanks in Advance, Mark
Sample code:
private void ImportFiles(string sourceFolderPath)
{
int numberOfRunningThreads;
int maxNumberThreads = 4;
//navigate through all of the files in this folder
FileInfo[] currentFolderFiles;
currentFolderFiles = new DirectoryInfo(sourceFolderPath)).GetFiles();
foreach (FileInfo currentFile in currentFolderFiles)
{
//make sure that we don’t exceed the number of threads specified
while (numberOfRunningThreads > (maxNumberThreads - 1))
{
//wait
Thread.Sleep(500);
}
//create a string array to pass to ImportFile
string[] importDetails = new string[2];
//set the array to the file name and the doc library path
importDetails[0] = currentFile.FullName;
importDetails[1] = destinationPath;
//assign the method to the callback to the ImportOneFile method
WaitCallback callBack = new WaitCallback(ImportOneFile);
//interlock increment the number of threads running
Interlocked.Increment(ref _numberOfRunningThreads);
//create a thread on the queue and provide the method with the
string array
ThreadPool.QueueUserWorkItem(callBack, (object)importDetails);
} //end of for loop
//make sure all of the threads are completed processing before leaving method
int loopCount = 0;
while ((_numberOfRunningThreads > 0) && (loopCount < 6000))
{
Thread.Sleep(50);
loopCount++;
}
if (loopCount > 5999)
{
throw new Exception(“Timeout waiting for threads to complete.â€);
}
}
private void ImportOneFile(object fileDetails)
{
//implement thread locking for protecting while using multithreading
lock(this)
{
//Using QueueUserWorkItem, parameters have to be sent to an object
// so here the parameters are repackaged in a string
string[] detailStrings = (string[])fileDetails;
//get an implementation of the file adder from the factory
CustomFileAdder fileAdder = new CustomFileAdder;
//add file, provide destination path, file name, contents
of file
fileAdder.AddFile(detailStrings[1],
Path.GetFileName(detailStrings[0]), BinaryFileContents(detailStrings[0]));
}
//interlock decrement since we are done
Interlocked.Decrement(ref _numberOfRunningThreads);
}
files to a new location in a way that improves performance of the client
windows application.
The problem occurs when 2 or more threads are created, the ImportOneFile
method attempts to add a previously added file. If I allow 4 maximum threads
and process 4 files, the last file is attempted 4 times and none of the other
files are added to the destination. If I reduce maximum threads to 2, the
second file is attempted twice, the first one is forgotten and other files
are added to the destination.
Anyone have any idea why the values passed to ImportOneFile are sometimes
"forgotten"? I thought the lock statement would protect against this.
Thanks in Advance, Mark
Sample code:
private void ImportFiles(string sourceFolderPath)
{
int numberOfRunningThreads;
int maxNumberThreads = 4;
//navigate through all of the files in this folder
FileInfo[] currentFolderFiles;
currentFolderFiles = new DirectoryInfo(sourceFolderPath)).GetFiles();
foreach (FileInfo currentFile in currentFolderFiles)
{
//make sure that we don’t exceed the number of threads specified
while (numberOfRunningThreads > (maxNumberThreads - 1))
{
//wait
Thread.Sleep(500);
}
//create a string array to pass to ImportFile
string[] importDetails = new string[2];
//set the array to the file name and the doc library path
importDetails[0] = currentFile.FullName;
importDetails[1] = destinationPath;
//assign the method to the callback to the ImportOneFile method
WaitCallback callBack = new WaitCallback(ImportOneFile);
//interlock increment the number of threads running
Interlocked.Increment(ref _numberOfRunningThreads);
//create a thread on the queue and provide the method with the
string array
ThreadPool.QueueUserWorkItem(callBack, (object)importDetails);
} //end of for loop
//make sure all of the threads are completed processing before leaving method
int loopCount = 0;
while ((_numberOfRunningThreads > 0) && (loopCount < 6000))
{
Thread.Sleep(50);
loopCount++;
}
if (loopCount > 5999)
{
throw new Exception(“Timeout waiting for threads to complete.â€);
}
}
private void ImportOneFile(object fileDetails)
{
//implement thread locking for protecting while using multithreading
lock(this)
{
//Using QueueUserWorkItem, parameters have to be sent to an object
// so here the parameters are repackaged in a string
string[] detailStrings = (string[])fileDetails;
//get an implementation of the file adder from the factory
CustomFileAdder fileAdder = new CustomFileAdder;
//add file, provide destination path, file name, contents
of file
fileAdder.AddFile(detailStrings[1],
Path.GetFileName(detailStrings[0]), BinaryFileContents(detailStrings[0]));
}
//interlock decrement since we are done
Interlocked.Decrement(ref _numberOfRunningThreads);
}