G
Guest
Hi All!
I'm developing in C# using .NET 2003 Enterprise Developer (.NET Framework
1.1.4322 SP1) running on Windows 2000.
I'm attempting to "lock" a file that's used by two processes by adding a
".LOK" extension to the end of the filename. When I rename the file in a
local directory using the System.IO.File.Move method, there seems to be a
slight delay between the time the file is renamed and the time that other
processes recognize that the change occurred. For example, I have two
instances of the same application running on the same machine (Process A and
Process B). Both processes are working with the same local file
(c:\temp\TestLockFile\TestFile.txt). Process A checks to see whether
TestFile.txt exists (in other words has not been renamed by Process B) using
the File.Exists method. If the file exists (has not been renamed by Process
B), Process A attempts to rename TestFile.txt to TestFile.txt.LOK using the
File.Move method.
Meanwhile, Process B is performing the same logic described above for
Process A. Inevitably, this leads to situations where Process A and Process
B check to see whether TestFile.txt exists using the File.Exists method at
almost the same instant. As expected, since neither process has renamed the
file yet, each process sees that TestFile.txt exists (has not been renamed by
the other process). However, the issue that I'm running into is that neither
process is throwing an error in these situations. Instead, each process
proceeds as if it was the one that renamed TestFile.txt. It seems to me, for
example, that if Process A executes the File.Move method even a millisecond
before Process B does, the File.Move method should throw a
FileNotFoundException in Process B (since Process A already renamed
TestFile.txt to TestFile.txt.LOK). Am I missing something? Is there a way
to ensure that both processes can't rename TestFile.txt at the same time? Or
is there perhaps a different proven approach to "locking" a file that's used
by multiple processes?
I'm able to reproduce the scenario above (most of the time) by forcing both
processes to rename TestFile.txt at almost the same instant using the
following code. Notice that the logic makes each process wait until the
system clock reaches the next minute.
private void LockFile(string strOriginalPath)
{
try
{
string strNewPath = strOriginalPath + ".LOK";
string strMessage = "";
//see if the original file exists
if(File.Exists(strOriginalPath))
{
//get the datetime object for the next minute and wait for it to
elapse
System.DateTime dtNow = System.DateTime.Now;
int iYear = dtNow.Year;
int iMonth = dtNow.Month;
int iDay = dtNow.Day;
int iHour = dtNow.Hour;
int iMinute = dtNow.Minute + 1;
System.DateTime dtNextMinute = new System.DateTime(iYear,
iMonth, iDay, iHour, iMinute, 0);
while(dtNextMinute.CompareTo(System.DateTime.Now) > 0)
{
//wait until calculated time (ie. next even minute on system
clock)...
}
//attempt to rename the file
File.Move(strOriginalPath, strNewPath);
//verify it was renamed
if(!File.Exists(strNewPath))
{
strMessage += "Unable to lock file " + strOriginalPath + ".";
throw new ApplicationException(strMessage);
}
}
else
{
//see if the file was already renamed
if(File.Exists(strNewPath))
strMessage += strOriginalPath + " already locked.";
else
strMessage += strOriginalPath + " does not exist.";
throw new ApplicationException(strMessage);
}
}
catch
{
throw;
}
}
Thanks in advance for your advice, Dave
I'm developing in C# using .NET 2003 Enterprise Developer (.NET Framework
1.1.4322 SP1) running on Windows 2000.
I'm attempting to "lock" a file that's used by two processes by adding a
".LOK" extension to the end of the filename. When I rename the file in a
local directory using the System.IO.File.Move method, there seems to be a
slight delay between the time the file is renamed and the time that other
processes recognize that the change occurred. For example, I have two
instances of the same application running on the same machine (Process A and
Process B). Both processes are working with the same local file
(c:\temp\TestLockFile\TestFile.txt). Process A checks to see whether
TestFile.txt exists (in other words has not been renamed by Process B) using
the File.Exists method. If the file exists (has not been renamed by Process
B), Process A attempts to rename TestFile.txt to TestFile.txt.LOK using the
File.Move method.
Meanwhile, Process B is performing the same logic described above for
Process A. Inevitably, this leads to situations where Process A and Process
B check to see whether TestFile.txt exists using the File.Exists method at
almost the same instant. As expected, since neither process has renamed the
file yet, each process sees that TestFile.txt exists (has not been renamed by
the other process). However, the issue that I'm running into is that neither
process is throwing an error in these situations. Instead, each process
proceeds as if it was the one that renamed TestFile.txt. It seems to me, for
example, that if Process A executes the File.Move method even a millisecond
before Process B does, the File.Move method should throw a
FileNotFoundException in Process B (since Process A already renamed
TestFile.txt to TestFile.txt.LOK). Am I missing something? Is there a way
to ensure that both processes can't rename TestFile.txt at the same time? Or
is there perhaps a different proven approach to "locking" a file that's used
by multiple processes?
I'm able to reproduce the scenario above (most of the time) by forcing both
processes to rename TestFile.txt at almost the same instant using the
following code. Notice that the logic makes each process wait until the
system clock reaches the next minute.
private void LockFile(string strOriginalPath)
{
try
{
string strNewPath = strOriginalPath + ".LOK";
string strMessage = "";
//see if the original file exists
if(File.Exists(strOriginalPath))
{
//get the datetime object for the next minute and wait for it to
elapse
System.DateTime dtNow = System.DateTime.Now;
int iYear = dtNow.Year;
int iMonth = dtNow.Month;
int iDay = dtNow.Day;
int iHour = dtNow.Hour;
int iMinute = dtNow.Minute + 1;
System.DateTime dtNextMinute = new System.DateTime(iYear,
iMonth, iDay, iHour, iMinute, 0);
while(dtNextMinute.CompareTo(System.DateTime.Now) > 0)
{
//wait until calculated time (ie. next even minute on system
clock)...
}
//attempt to rename the file
File.Move(strOriginalPath, strNewPath);
//verify it was renamed
if(!File.Exists(strNewPath))
{
strMessage += "Unable to lock file " + strOriginalPath + ".";
throw new ApplicationException(strMessage);
}
}
else
{
//see if the file was already renamed
if(File.Exists(strNewPath))
strMessage += strOriginalPath + " already locked.";
else
strMessage += strOriginalPath + " does not exist.";
throw new ApplicationException(strMessage);
}
}
catch
{
throw;
}
}
Thanks in advance for your advice, Dave