views:

649

answers:

6

Hi,

In a asp.net web application, I want to write to a file. This function will first get data from the database, and then write out the flat file.

What can I do to make sure only 1 write occurs, and once the write occurrs, the other threads that maybe want to write to the file don't since the write took place.

I want to have this write done ONLY if it hasn't been done in say 15 minutes.

I know there is a lock keyword, so should I wrap everything in a lock, then check if it has been updated in 15 minutes or more, or visa versa?

Update

Workflow:

Since this is a web application, the multiple instances will be people viewing a particular web page. I could use the build in cache system, but if asp.net recycles it will be expensive to rebuild the cache so I just want to write it out to a flat file. My other option would be just to create a windows service, but that is more work to manage that I want.

+1  A: 

Synchronize your writing code to lock on a shared object so that only one thread gets inside the block. Others wait till the current one exits.

lock(this)
{
  // perform the write.
}

Update: I assumed that you have a shared object. If these are different processes on the same machine, you'd need something like a Named Mutex. Looky here for an example

Gishu
I think this wouldn't work, for reasons I've explained below.
MarkR
+1  A: 

is it not better to lock an object variable rather than the whole instance?

redsquare
A: 

I'm not convinced that .NET's locking is applicable to different processes. Moreover, lock(this) will only exclude other threads that are running the method on the same instance of "this" - so other threads even in the same process could run at once on different instances.

Assuming all your processes are running on the same machine, file locking should do it though.

If you're on different machines, your mileage may vary- win32 claims to have file locking which works over a network, but historically applications which rely on it (Think MSAccess) have problems with file corruption anyway.

MarkR
A: 
   // try enter will return false if another thread owns the lock
   if (Monitor.TryEnter(lockObj))
   {
      try
      {
         // check last write time here, return if too soon; otherwise, write
      }
      finally
      {
         Monitor.Exit(lockobj);
      }
   }
omellet
that is the exact same thing as lock(lockObj) { }.
Nicholas Mancuso
+1  A: 

File I/O operations that write to the file will automatically lock the file. Check if the file is locked (by trying the write) and if it is do not write. Before doing any writes, check the timestamp on the file and see if its more than 15 minutes.

afaik you can not write to a file without it being locked by Windows/whatever.

Now all that's left for you is to look up how to do the above using msdn (sorry, I can't be bothered to look it all up and I don't remember the C# classes very well). :)

jheriko
A: 

Use file-system locks

Like others suggested, .NET locks will be of limited use in this situation. Here is the code:

FileInfo fi = new FileInfo(path);
if (fi.Exists
    && (DateTime.UtcNow - fi.LastWriteTimeUtc < TimeSpan.FromMinutes(15)) {
  // file is fresh
  return;
}

FileStream fs;
try {
  fs = new FileStream(
    path, FileMode.Create, FileAccess.Write, FileShare.Read);
} catch (IOException) {
  // file is locked
  return;
}

using (fs) {
  // write to file
}

This will work across threads and processes.

Constantin