Хотите записать в файл, но потенциально может иметь несколько писателей одновременно, необходимо заблокировать - PullRequest
6 голосов
/ 18 сентября 2008

В веб-приложении asp.net я хочу записать в файл. Эта функция сначала получает данные из базы данных, а затем записывает плоский файл.

Что я могу сделать, чтобы убедиться, что происходит только 1 запись, и как только запись происходит, другие потоки, которые, возможно, захотят записать в файл, не будут, поскольку запись произошла.

Я хочу, чтобы эта запись была сделана ТОЛЬКО, если она не была сделана, скажем, за 15 минут.

Я знаю, что есть ключевое слово блокировки, так что я должен обернуть все в блокировку, а затем проверить, было ли оно обновлено через 15 минут или более, или наоборот?

Обновление

Workflow:

Поскольку это веб-приложение, в нескольких случаях пользователи будут просматривать определенную веб-страницу. Я мог бы использовать встроенную систему кэширования, но если asp.net перезапустит процесс восстановления кэша, будет дорого, поэтому я просто хочу записать его в плоский файл. Другим моим вариантом было бы просто создать службу Windows, но это больше работы для управления, чем я хочу.

Ответы [ 7 ]

2 голосов
/ 18 сентября 2008

Синхронизируйте код написания, чтобы заблокировать общий объект, чтобы в блок попадал только один поток Другие ждут, пока выйдет текущий.

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

Обновление: я предположил, что у вас есть общий объект. Если это разные процессы на одной машине, вам понадобится что-то вроде Named Mutex. Посмотрите здесь пример

1 голос
/ 18 сентября 2008

Операции ввода-вывода файла, которые записывают в файл, автоматически блокируют файл. Проверьте, заблокирован ли файл (при попытке записи), и если он не записан. Прежде чем делать какие-либо записи, проверьте метку времени в файле и посмотрите, превышает ли она 15 минут.

afaik вы не можете записать в файл, если он не заблокирован Windows / что угодно.

Теперь все, что вам осталось, это посмотреть, как это сделать, используя msdn (извините, я не могу потрудиться посмотреть все это и не очень хорошо помню классы C #). :)

1 голос
/ 18 сентября 2008

не лучше ли заблокировать переменную объекта, а не весь экземпляр?

0 голосов
/ 25 марта 2011

Вы, ребята, должны рассмотреть Mutex . Он может синхронизироваться между несколькими потоками и процессами.

0 голосов
/ 04 октября 2008

Использовать блокировки файловой системы

Как и другие, в этой ситуации блокировки .NET будут иметь ограниченное применение. Вот код:

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
}

Это будет работать в процессах и .

0 голосов
/ 18 сентября 2008
   // 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);
      }
   }
0 голосов
/ 18 сентября 2008

Я не уверен, что блокировка .NET применима к различным процессам. Более того, блокировка (this) будет исключать только другие потоки, которые запускают метод на одном и том же экземпляре «this», поэтому другие потоки, даже в одном и том же процессе, могут одновременно выполняться на разных экземплярах.

Предполагая, что все ваши процессы выполняются на одном компьютере, блокировка файлов должна это делать.

Если вы находитесь на разных машинах, ваш пробег может варьироваться - win32 утверждает, что имеет блокировку файлов, которая работает по сети, но исторически приложения, которые полагаются на это (Think MSAccess), все равно имели проблемы с повреждением файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...