Является ли CreateDirectory() в С# потокобезопасным?

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

Обратите внимание, что согласно MSDN, это нормально, чтобы вызвать CreateDirectory() в каталоге, который уже существует, и в этом случае метод как ожидается, ничего не сделает.

Ответ 1

Сам вызов Directory.CreateDirectory безопасен для создания нескольких потоков. Если вы это сделаете, это не повредит состояние программы или файловой системы.

Однако невозможно вызвать Directory.CreateDirectory таким образом, чтобы гарантировать, что он не будет генерировать исключение. Файловая система представляет собой непредсказуемый зверь, который может быть изменен другими программами вне вашего контроля в любой момент времени. Очень возможно, например, увидеть следующее:

  • Программа 1 Тема 1: Вызов CreateDirectory для c:\temp\foo, и она преуспевает
  • Программа 2 Тема 1: Удаляет доступ к c:\temp от пользователя программы 1
  • Программа 1 Тема 2: Вызов CreateDirectory и выбрасывается из-за недостаточного доступа

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

Ответ 2

Из документов MSDN в Каталоге:

Все публичные статические (Shared in Visual Basic) члены этого типа являются потокобезопасными. Любые члены экземпляра не гарантируют безопасность потоков.

Поэтому, поскольку CreateDirectory является статическим, да, он является потокобезопасным.

Это говорит: как указывает @JaredPar, проблемы безопасности потоков - не единственная причина, по которой метод может генерировать исключения. Существует множество причин, по которым вызов файловой системы может вызывать исключение (при любых обстоятельствах, многопоточность или нет), и вам нужно учитывать их.

Говоря, что это потокобезопасный я (и MSDN), подразумевает только буквальную интерпретацию этого, что означает, что этот метод не изменяет состояние общей программы таким образом, чтобы обычно приводить к недействительному состоянию, условиям гонки или другим неблагоприятным последствиям связанных с небезопасным многопоточным кодом "

Ответ 3

Чтобы уточнить ответ @JaredPar, у вас есть состояние гонки на ваших руках. Если первый вызов создает папку полностью, и только тогда начинается второй вызов, все будет ОК.

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

Он по-прежнему является потокобезопасным в том смысле, что вы не получите никаких непредсказуемых папок, созданных или вообще не имеющих папки.

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

Итак, ваша эвристика, чтобы быть абсолютно уверенной, должна быть такой:

  • Создать каталог
  • Если это не удается, подождите некоторое время (скажем, от 0,2 до 0,5 секунды) и повторите попытку.
  • Если он терпит неудачу постоянно (скажем, 3 раза подряд), у вас есть еще одна проблема в ваших руках - никаких прав доступа к папке, полного диска и т.д.

    Кстати, почему бы не создать папку один раз, когда приложение запустится?