CreateDirectory() в C# потокобезопасен?

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

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

3 ответа

Решение

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

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

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

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

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

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

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

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

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

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

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

Это все еще потокобезопасный в том смысле, что вы не получите никаких непредсказуемых папок или вообще никаких папок.

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

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

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

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

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