Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> "Безопасная" работа с файлами 
:(
    Опции темы
Pankon
Дата 17.12.2007, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



"Безопасная" работа с файлами.

Несколько процессов интенсивно "заполнают" текстовый файл. По достижении определенного размера, один из процессов переименовывает файл. Примерно так:
Код

FileInfo fileInfo = new System.IO.FileInfo("c:\\t.txt");
.....
fileInfo.MoveTo("c:\\t_1.txt");

Существует вероятность того, что между этими двумя командами(см. ваше) другой процесс обратится к файлу чтоб записать данные и тоже "захочет" его переименивать. (Что очень не желательно.)

Как этого избежать?





Это сообщение отредактировал(а) Pankon - 17.12.2007, 13:34
PM MAIL   Вверх
tol05
Дата 17.12.2007, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



когда один процесс работает с файлом и другой пытается в этом файле что-то изменить - то обычно выбрасывается Exception "Access denied".

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

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

Это сообщение отредактировал(а) tol05 - 17.12.2007, 13:43


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Pankon
Дата 17.12.2007, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



Цитата(tol05 @  17.12.2007,  13:42 Найти цитируемый пост)
лочить
  это что?



PM MAIL   Вверх
HalkaR
Дата 17.12.2007, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Пуфыстый назгул
****


Профиль
Группа: Экс. модератор
Сообщений: 2132
Регистрация: 8.12.2002
Где: В Москве

Репутация: 14
Всего: 42



Если это твои программы, то проще всего сделать программу-прокси, которая будет получать запросы, создавать очередь записи и записывать данные.
PM MAIL   Вверх
tol05
Дата 17.12.2007, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



лочить - это использовать lock (если у тебя несколько потоков работают с файлом).
Можно и через очереди работать, как сказал, HalkaR...


Pankon, а ты не хочешь рассказать, что это за процессы, что вообще делается? А то трудно угадывать решение проблемы.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Wizard_Memfis
Дата 17.12.2007, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 12.2.2007
Где: г. Донецк, Украин а

Репутация: 1
Всего: 4



Лочить - использовать кл. слово 
Код
lock 
. Тогда к данному объекту будет иметь только один процесс, а доступен объект станет, когда этот процесс покинет область lock
Опоздал!!! smile  smile 

Это сообщение отредактировал(а) Wizard_Memfis - 17.12.2007, 14:11
--------------------
www.binary-studio.com
PM MAIL WWW ICQ Skype   Вверх
Pankon
Дата 17.12.2007, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



Цитата(tol05 @  17.12.2007,  14:08 Найти цитируемый пост)
трудно угадывать

На сервере несколько приложений(АСПХ-ы, вебсервисы, винсервис ) "заполнают" текстовый файл, для этого написана одна длл, копия которой используется во всех приложениях, (положить в ГАК не предлогатьsmile ). 
С одновремменным доступом борюсь с помощью последовательных слееп, в процессах, пока файл не будет "свободен" - решение не нравится, но пока ничего другого не нашел...

Если файл достигает определенного размера, один из процессов переименовывает файл (а затем архиварует).

При сохранении задаю монопольный доступ (open) и все работает, но после close, доступ то "нормальный" и другие процессы имеют снова доступ к файлу и могут что-либо записывать в файл, а в это время "первый" переименовывает файл ну т.д.

Добавлено через 2 минуты и 23 секунды
Цитата(Wizard_Memfis @  17.12.2007,  14:10 Найти цитируемый пост)
только один процесс
  процессы в разных приложениях.....

PM MAIL   Вверх
tol05
Дата 17.12.2007, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Ну если работа идет через одну и ту же библиотеку, то почему бы в ней не сделать статическое поле-флаг, которое и будет говорить, работают с файлом или нет? 
Как только любой из процессов (работающих с файлом через эту dll) занимает файл, то он этот флаг устанавливает. Остальные процессы - считывают значение флага и ждут. А потом процесс освобождает файл и сбрасывает флаг.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
1stain
Дата 17.12.2007, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 486
Регистрация: 30.7.2007
Где: Киев - Харьков

Репутация: 8
Всего: 40



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

что такое синглтон


--------------------
Все знают, что это невозможно. Но вот приходит невежда, которому это неизвестно - он-то и делает открытие. (Albert Einstein)
user posted image
PM MAIL   Вверх
tol05
Дата 17.12.2007, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Гм... я счас подумал... не годится ни мой вариант, ни твой, 1stain. Процессы разные могут быть... А значит и домены, и сборки, и память...

Стопроцентный вариант - работа через environment variables, но я на нем не настаиваю. Предлагайте лучшие smile


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Pankon
Дата 17.12.2007, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



Цитата(1stain @  17.12.2007,  14:57 Найти цитируемый пост)
паттерна синглтон

Цитата(tol05 @  17.12.2007,  15:00 Найти цитируемый пост)
не годится ни мой вариант, ни твой
 - правильно... Проложения - разные и используют разные копии длл


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

PM MAIL   Вверх
Experimenter
Дата 18.12.2007, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 430
Регистрация: 8.5.2007
Где: Уфа

Репутация: 8
Всего: 17



в VB есть класс Microsoft.VisualBasic.Logging.FileLogTraceListener, в C# почему-то нету, но можно референс поставить - очень удобный для записи и потокобезопасный класс.
Код

        static void WriteMessage(string message)
        {
            Microsoft.VisualBasic.Logging.FileLogTraceListener listener = new Microsoft.VisualBasic.Logging.FileLogTraceListener();
            listener.BaseFileName = "MyEvents"; //расширение автоматически будет .log
            listener.Append = true;
            listener.AutoFlush = true;
            listener.CustomLocation = AppDomain.CurrentDomain.BaseDirectory; //указывай свою папку
            listener.LogFileCreationSchedule = Microsoft.VisualBasic.Logging.LogFileCreationScheduleOption.Daily; //создает новый файл каждый день
            listener.WriteLine(message);
            listener.Close();
        }
хотя тоже не факт, что разные приложения его смогут использовать, я не проверял.

Это сообщение отредактировал(а) Experimenter - 18.12.2007, 14:04


--------------------
public Zlo FromTwoEvilsChooseSmaller(Zlo zlo1, Zlo zlo2){
    if(zlo1 < zlo2) return zlo1;
    else if(zlo1 > zlo2) return zlo2;
    else throw new Exception("Kill yourself by the wall"); }
PM WWW ICQ   Вверх
mr.DUDA
Дата 19.12.2007, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



А почему бы не юзать CopyTo вместо MoveTo? Закрыл файл, скопировал под новым именем, открыл заново, попробовал старый удалить (если вылетело исключение - обработать catch'ем, значит кто-то ещё юзает файл).


--------------------
user posted image
PM MAIL WWW   Вверх
Pankon
Дата 19.12.2007, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



Цитата(mr.DUDA @  19.12.2007,  15:33 Найти цитируемый пост)
Закрыл файл, скопировал под новым именем, открыл заново, попробовал старый удалить (если вылетело исключение - обработать catch'ем, значит кто-то ещё юзает файл). 
 

(1 процесс)А если между "Закрыл файл" и "попробовал старый удалить" другой процесс(2 процесс) успел сохранить че-нибудь и закрыть(что бы самому - "скопировал... попробовал удалить..."), тогда 1 процесс делает успешно "попробовал старый удалить" и данные, которые записал второй процесс будут утеряны...

(И как же будет удивлен 2 процесс, когда захочет "скопировал под новым именем", а фаила уже нет.....)
PM MAIL   Вверх
tol05
Дата 19.12.2007, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Pankon, я же предлагал надежный способ. В свою dll вставь
Код

string fileIsBusy = Environment.GetEnvironmentVariable("FileIsBusy");
bool busy;

if(String.IsNullOrEmpty(fileIsBusy))
{
       busy = false;
}
else
{
       Boolean.TryParse(fileIsBusy, out busy);
}
if(!busy)
{
       Environment.SetEnvironmentVariable("FileIsBusy", "true");
       //работаем с файлом
       Environment.SetEnvironmentVariable("FileIsBusy", "false");
}
return; 

чем не устраивает?


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0581 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.