Как управлять одновременным доступом ввода / вывода к XML-файлу из нескольких экземпляров EXE, используя Delphi. - PullRequest
5 голосов
/ 19 сентября 2008

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

Для достижения этой цели я ввел простой файл "mutex" - инструмент создает один временный файл перед записью в XML, а затем удаляет временный файл после завершения копирования. Поэтому, если выполняется другой экземпляр, он проверяет наличие этого временного файла и ожидает его удаления. Затем он снова создает временный файл, записывает в XML и удаляет временный файл.

Проблема в том, что это работает нормально только тогда, когда 2-3 экземпляра пытаются одновременно записать в файл XML. Когда есть больше экземпляров - некоторые из них просто ждут вечно и никогда не добавляют узел в XML.

Есть ли лучший способ заставить его работать с большим количеством экземпляров, работающих и записывающих в XML одновременно?

Ответы [ 5 ]

6 голосов
/ 19 сентября 2008

Именованный семафор или мьютекс может сделать это для вас на одной машине. Используйте, например, TMutex от SyncObjs, и используйте один из конструкторов, который принимает аргумент имени. Если вы используете одно и то же имя во всех приложениях, они будут синхронизироваться по одному мьютексу ядра. Используйте TMutex.Acquire для доступа и TMutex.Release, когда вы закончите, защищенный в блоке try / finally.

Используйте перегрузку TMutex.Create, которая имеет аргумент InitialOwner, но для этого укажите False (если, конечно, вы не хотите сразу получить мьютекс). Эта перегрузка вызывает CreateMutex за кулисами. Обратитесь к источнику SyncObjs и документации для CreateMutex для получения дополнительной информации.

4 голосов
/ 19 сентября 2008

1 - настроить файл, в котором записываются ожидающие изменения (он будет работать как очередь)

2 - Напишите простое приложение для просмотра этого файла и примените изменения к файлу XML

3 - Изменить текущий инструмент командной строки, чтобы добавить свои запросы на изменение в файл «Ожидающие изменения»

Теперь только одно приложение должно касаться окончательного XML-файла.

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

TXMLDocument уже предотвращает одновременную запись нескольких экземпляров в один и тот же файл. Поэтому я предполагаю, что на самом деле ваш вопрос означает: «Как я могу открыть документ XML для чтения, запретить другим экземплярам записывать в документ во время чтения , а затем записывать документ, прежде чем позволить другим экземплярам сделать то же самое? "

В этом случае вам следует самостоятельно открывать и закрывать файл, а не позволять TXMLDocument сделать это за вас. Используйте TFileStream, чтобы открыть файл с эксклюзивной блокировкой чтения и записи и XMLDocument.LoadFromStream вместо LoadFromFile. Сохраните документ с помощью SaveToStream после сброса потока. Установите на 0. Используйте try / finally, чтобы убедиться, что вы закрыли поток, когда закончили с ним. Поскольку вы блокируете файл исключительно, вам больше не нужен временный файл или любой другой вид мьютекса.

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

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

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

Подход к записи в отдельный файл представляет собой интересное решение, которое следует рассмотреть, если бы ваши приложения с несколькими экземплярами записывали уникальные файлы XML, а затем загружали их в основной документ с помощью отдельной программы, используя цикл FindFirst. Таким образом, вы можете сохранить свою структуру xml практически без изменений без существенных изменений в существующих программах.

0 голосов
/ 18 декабря 2011

С этот ответ :

В Windows это возможно, если вы можете управлять обеими программами. LockFileEx. Для чтения откройте общую блокировку в файле блокировки. Для записи, открыть эксклюзивный замок на файл блокировки. Блокировка странная в Windows, поэтому я рекомендую использовать для этого отдельный файл блокировки.

(«Обе программы» не применимы в вашем случае, поскольку это одна и та же программа, только запущенная в нескольких случаях.)

Дополнительное примечание / как я нашел этот ответ: Библиотека журналов Java logback использует API блокировки файлов для конкретной платформы (через NIO) для реализации «1013 * благоразумного режима », где несколько процессов может войти в один и тот же файл, не повредив его - что не возможно с операциями с файлами RTL Delphi.

...