Хотите записать в файл, но потенциально может иметь несколько писателей одновременно, необходимо заблокировать

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

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

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

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

Обновлять

Рабочий процесс:

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

Все ли записи происходят в одном экземпляре одного приложения? Или несколько экземпляров приложения будут пытаться писать одновременно, или разные приложения будут пытаться писать одновременно?

Alex B 18.09.2008 19:34
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
1
3 575
7

Ответы 7

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

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

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

Я думаю, что это не сработает по причинам, которые я объяснил ниже.

MarkR 18.09.2008 19:36

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

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

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

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

Вы правы, что для того, чтобы блокировка сработала, вам понадобятся все методы для использования одного и того же экземпляра this. Решением здесь может быть создание экземпляра фиктивного объекта статический, который обеспечит это.

Ivan Nikolov 21.01.2012 22:09

   // 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);
      }
   }

это то же самое, что и lock (lockObj) {}.

Nicholas Mancuso 04.10.2008 19:34

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

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

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

Обратите внимание: мой ответ зависит от надежности временных меток - не всегда хорошее предположение. Вместо этого вы можете оставить файл открытым, чтобы в него не производилась запись в течение 15 минут после того, как какой-либо процесс завершит запись. :)

jheriko 19.03.2012 07:59

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

Как и другие предположения, блокировки .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
}

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

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

Другие вопросы по теме