A
atlaste
Hi,
I have two different things I'd like to discuss here. Both are about
cross-process synchronization of shared resources. The resources that
are shared are: (1) an object writing to a file and (2) a file. I
threat them as two different problems for various reasons.
The first problem involves the object writing to a file. The problem
might be best explained by thinking of a single log file that's
appended by different programs that interoperate. If we would do
nothing the file would be opened by the programs simultaneously and
written simultaneously, yielding incorrect log entries.
It is my understanding that types from the CLR are not shared and can
thus be used for locking the logging object. So in the logging object
we should be able to handle the condition as follows:
// locks the type of the logging object
lock (typeof(this))
{
// some code to demonstrate the idea...
StreamWriter sw = new StreamWriter(filename, true);
sw.WriteLine("{0}", logline);
sw.Close();
}
Since only this object should be responsible for writing the file,
this should work. If another object locks the file, the type won't be
locked, hence the StreamWriter will throw an exception. If another
program attempts to use the object and write an entry, it will run
into the lock.
I'd like to discuss if this is the/an appropriate way to handle this
problem and why.
The second point of discussion is in locking files between processes.
As far as I know the only way to do this properly is by checking if
the file is available on intervals and if so opening it. Since it is
important to open the file and thereby locking it instantly I believe
the way of doing that properly is wrapping the FileStream as follows:
// -- below is the wrapper class
public class LockingFileStream : IDisposable {
private FileStream fs = null;
public LockingFileStream(string filename) : base()
{
while (fs == null)
{
try
{
fs = File.Open(filename, FileMode.Open, FileAccess.ReadWrite,
FileShare.None);
}
catch (IOException e)
{
System.Threading.Thread.Sleep(1000);
}
}
public FileStream Handle { get { return fs; } }
public void Dispose()
{
// make sure we release the lock here
if (fs != null)
{
fs.Close();
fs.Dispose();
fs = null;
}
}
}
// -- above is the wrapper; here follows a piece of code that uses it
void MyTest()
{
using (LockingFileStream lfs = new LockingFileStream(myFilename))
{
// use lfs.Handle
}
}
// -------
However, this code polls the file to see if it's locked or not. I'd
rather use a monitor or mutex alike construction if that's in any way
possible.
Suggestions?
Cheers,
Stefan de Bruijn
I have two different things I'd like to discuss here. Both are about
cross-process synchronization of shared resources. The resources that
are shared are: (1) an object writing to a file and (2) a file. I
threat them as two different problems for various reasons.
The first problem involves the object writing to a file. The problem
might be best explained by thinking of a single log file that's
appended by different programs that interoperate. If we would do
nothing the file would be opened by the programs simultaneously and
written simultaneously, yielding incorrect log entries.
It is my understanding that types from the CLR are not shared and can
thus be used for locking the logging object. So in the logging object
we should be able to handle the condition as follows:
// locks the type of the logging object
lock (typeof(this))
{
// some code to demonstrate the idea...
StreamWriter sw = new StreamWriter(filename, true);
sw.WriteLine("{0}", logline);
sw.Close();
}
Since only this object should be responsible for writing the file,
this should work. If another object locks the file, the type won't be
locked, hence the StreamWriter will throw an exception. If another
program attempts to use the object and write an entry, it will run
into the lock.
I'd like to discuss if this is the/an appropriate way to handle this
problem and why.
The second point of discussion is in locking files between processes.
As far as I know the only way to do this properly is by checking if
the file is available on intervals and if so opening it. Since it is
important to open the file and thereby locking it instantly I believe
the way of doing that properly is wrapping the FileStream as follows:
// -- below is the wrapper class
public class LockingFileStream : IDisposable {
private FileStream fs = null;
public LockingFileStream(string filename) : base()
{
while (fs == null)
{
try
{
fs = File.Open(filename, FileMode.Open, FileAccess.ReadWrite,
FileShare.None);
}
catch (IOException e)
{
System.Threading.Thread.Sleep(1000);
}
}
public FileStream Handle { get { return fs; } }
public void Dispose()
{
// make sure we release the lock here
if (fs != null)
{
fs.Close();
fs.Dispose();
fs = null;
}
}
}
// -- above is the wrapper; here follows a piece of code that uses it
void MyTest()
{
using (LockingFileStream lfs = new LockingFileStream(myFilename))
{
// use lfs.Handle
}
}
// -------
However, this code polls the file to see if it's locked or not. I'd
rather use a monitor or mutex alike construction if that's in any way
possible.
Suggestions?
Cheers,
Stefan de Bruijn