Доступ к единственному файлу с несколькими потоками

Можно добавить отделение с runat = "сервер" к странице:

<div runat="server" id="myDiv">
</div>

и затем набор его свойство InnerHtml от кода - позади:

myDiv.InnerHtml = "your html here";

, Если Вы хотите изменить содержание DIV на стороне клиента, тогда можно использовать код JavaScript, подобный этому:

<script type="text/javascript">
    Sys.Application.add_load(MyLoad);
    function MyLoad(sender) {
        $get('<%= div.ClientID %>').innerHTML += " - text added on client";
    }
</script>
17
задан Raymond Wilson 27 October 2009 в 18:46
поделиться

4 ответа

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

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

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

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

Указание File_Flag_Delete_On_Close означает, что все последующие открытые запросы должны совместно использовать файл для удаления. Снова документация:

Последующие запросы на открытие файла завершаются ошибкой, если не указан режим общего доступа FILE_SHARE_DELETE .

Затем, поскольку второй открытый запрос разделяет файл для удаления, все другие открытые дескрипторы также должны совместно использовать его для удаления. Документация:

Если существуют открытые дескрипторы файла, вызов завершится ошибкой, если все они не были открыты в режиме общего доступа FILE_SHARE_DELETE .

Суть в том, что либо все имеют одинаковый доступ, либо никто

FFileSystem := CreateFile(PChar(FFileName),
  Generic_Read or Generic_Write
  File_Share_Read or File_Share_Write or File_Share_Delete,
  nil,
  Create_Always,
  File_Attribute_Normal or File_Flag_Random_Access
    or File_Attribute_Temporary or File_Flag_Delete_On_Close,
  0);

FFileSystem2 := CreateFile(PChar(FFileName),
  Generic_Read,
  File_Share_Read or File_Share_Write or File_Share_Delete,
  nil,
  Open_Existing,
  File_Attribute_Normal or File_Flag_Random_Access
    or File_Attribute_Temporary or File_Flag_Delete_On_Close,
  0);

Другими словами, все параметры одинаковы, за исключением пятого.

Эти правила применяются к двум попыткам открытия в одном и том же потоке, а также попыткам из разных темы.

18
ответ дан 30 November 2019 в 12:58
поделиться

Вы можете сделать так ...

Первый поток с доступом для чтения / записи должен сначала создать файл:

FileHandle := CreateFile(
  PChar(FileName),
  GENERIC_READ or GENERIC_WRITE,
  FILE_SHARE_READ,
  nil,
  CREATE_ALWAYS,
  FILE_ATTRIBUTE_NORMAL,
  0);

Второй поток с доступом только для чтения, затем открывает тот же файл:

  FileHandle := CreateFile(
    PCHar(FileName),
    GENERIC_READ,
    FILE_SHARE_READ + FILE_SHARE_WRITE,
    nil,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    0);

Я не проверял, работает ли с ...

FILE_ATTRIBUTE_TEMPORARY,
FILE_FLAG_DELETE_ON_CLOSE

атрибутами ...

2
ответ дан 30 November 2019 в 12:58
поделиться

Мне нужно получить доступ к файлу одновременно с несколькими потоками. Это нужно делать одновременно, без сериализации потоков по соображениям производительности.

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

В противном случае вы просто готовясь к душевной боли в будущем.

1
ответ дан 30 November 2019 в 12:58
поделиться

Обновление # 2

Я написал несколько тестовых проектов на C, чтобы попытаться понять это, хотя Роб Кеннеди опередил меня, пока я был в отъезде. Оба условия возможны, включая перекрестный процесс, как он подчеркивает. Вот ссылка, если кто-то еще хотел бы увидеть это в действии.

SharedFileTests.zip (VS2005 C ++ Solution) @ meklarian.com

Есть три проекта:

InProcessThreadShareTest - Тестирование создателя и клиентского потока. SharedFileClient - создайте клиента, который работает в течение 30 секунд и опрашивает файл.
SharedFileHost.cpp и SharedFileClient.cpp Snippet @ gist.github

Все эти проекты предполагают расположение C: \ data \ tmp \ sharetest.txt можно создавать и записывать.


Обновление

Судя по вашему сценарию, вам нужен очень большой кусок памяти. Вместо того, чтобы играть в системный кеш, вы можете использовать AWE для доступа к более чем 4 ГБ памяти, хотя вам нужно будет отображать части за раз. Это должно охватывать ваш сценарий L2, поскольку вы хотите убедиться, что используется физическая память.

Address Windowing Extensions @ MSDN

Используйте AllocateUserPhysicalPages и VirtualAlloc для резервирования памяти.

Функция AllocateUserPhysicalPages (Windows) @ MSDN
Функция VirtualAlloc (Windows) @ MSDN


Исходная

Учитывая, что вы используете флаг FILE_FLAG_DELETE_ON_CLOSE, есть ли причина, по которой вы не стали бы использовать отображение памяти? файл?

Управление файлами с отображением памяти в Win32 @ MSDN

Из того, что я вижу в ваших инструкциях CreateFile, похоже, что вы хотите обмениваться данными между потоками или между процессами, имея в виду только одинаковые файл присутствует, пока открыты все сеансы. Файл с отображением памяти позволяет использовать одно и то же логическое имя файла во всех сеансах. Еще одно преимущество заключается в том, что вы можете отображать представления и блокировать части сопоставленного файла с безопасностью во всех сеансах. Если у вас есть строгий сервер со сценарием с N-клиентом, это должно быть легко реализовать. Если у вас есть случай, когда любой клиент может быть открывающим сервером, вы можете рассмотреть возможность использования какого-либо другого механизма, чтобы гарантировать, что только один клиент сможет сначала инициировать обслуживающий файл (возможно, через глобальный мьютекс).

CreateMutex @ MSDN

Если вам нужна только односторонняя передача данных, возможно, вы могли бы использовать вместо этого именованные каналы.
(edit) Это лучше всего для 1 сервера на 1 клиента.

Именованные каналы (Windows) @ MSDN

6
ответ дан 30 November 2019 в 12:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: