We have an heavily used .Net 3.5 application that reads “expensive to create” data and caches it. The application reads\writes files based on it not “being used by another process”. If some other process is reading and writing to the file, then the application goes to sleep(for some time) and retries. Is this a correct way of reading and writing files? Please advise.
public void Add<T>(string key, CacheItem<T> item)
{
bool fileInUse = false;
while (!fileInUse)
{
try
{
using (Stream stream = new FileStream(Path.Combine(cachePath, key+".bin"), FileMode.Create, FileAccess.Write, FileShare.None))
{
Serializer.NonGeneric.Serialize(stream, item);
}
fileInUse = true;
}
catch (IOException ex)
{
if (ex.Message.Contains("being used by another process"))
{
//Poll till the file is free to be used by this process
Thread.Sleep(100);
fileInUse = false;
}
}
}
}
public CacheItem<T> Get<T>(string key, Type type)
{
CacheItem<T> item = null;
FileInfo fileInfo = new FileInfo(Path.Combine(cachePath, key+".bin"));
fileInfo.Refresh();
if (fileInfo.Exists)
{
bool fileInUse = false;
while (!fileInUse)
{
try
{
using (Stream stream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.None))
{
object objectTemp = Serializer.NonGeneric.Deserialize(type, stream);
item = (CacheItem<T>)objectTemp;
}
fileInUse = true;
}
catch(IOException ex)
{
if (ex.Message.Contains("being used by another process"))
{
//Poll till the file is free to be used by this process
Thread.Sleep(100);
fileInUse = false;
}
}
}
}
return item;
}
You could add a global mutex on top of it, to avoid waiting more than absolutely necessary.
Global mutex is created by passing a non-empty
nameto Mutex Constructor.Benefits:
All in all, you are not just going to be faster, you’ll likely consume less CPU cycles in the process.