简体   繁体   English

CreateDirectory()在C#中是否是线程安全的?

[英]Is CreateDirectory() in C# thread-safe?

Can I safely attempt to create the same directory from two different threads, without having one of them throw an exception, or run into other issues? 我可以安全地尝试从两个不同的线程创建相同的目录,而不会让其中一个抛出异常,或遇到其他问题吗?

Note that according to MSDN , it is OK to call CreateDirectory() on a directory which already exists, in which case the method is expected to do nothing. 请注意,根据MSDN ,可以在已存在的目录上调用CreateDirectory() ,在这种情况下,该方法不会执行任何操作。

The Directory.CreateDirectory call itself is safe to make from multiple threads. Directory.CreateDirectory调用本身可以安全地从多个线程进行。 It will not corrupt program or file system state if you do so. 如果这样做,它不会破坏程序或文件系统状态。

However it's not possible to call Directory.CreateDirectory in such a way to guarantee it won't throw an exception. 但是,无法以这种方式调用Directory.CreateDirectory以保证它不会抛出异常。 The file system is an unpredictable beast which can be changed by other programs outside your control at any given time. 文件系统是一个不可预测的野兽,可以在任何给定时间由您控制之外的其他程序更改。 It's very possible for example to see the following occur 例如,很可能看到以下情况发生

  • Program 1 Thread 1: Call CreateDirectory for c:\\temp\\foo and it succeeds 程序1线程1:为c:\\temp\\foo调用CreateDirectory并成功
  • Program 2 Thread 1: Removes access to c:\\temp from program 1 user 程序2线程1:从程序1用户中删除对c:\\temp访问权限
  • Program 1 Thread 2: Call CreateDirectory and throws due to insufficient access 程序1线程2:调用CreateDirectory并因访问不足而抛出

In short you must assume that Directory.CreateDirectory , or really any function which touches the file system, can and will throw and handle accordingly. 简而言之,您必须假设Directory.CreateDirectory ,或者实际上任何触及文件系统的函数都可以并且将相应地抛出和处理。

From the MSDN docs on Directory : 目录上MSDN文档

Any public static (Shared in Visual Basic) members of this type are thread safe. 此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。 Any instance members are not guaranteed to be thread safe. 任何实例成员都不保证是线程安全的。

Therefore, as CreateDirectory is static, yes, it is thread safe. 因此,由于CreateDirectory是静态的,是的,它是线程安全的。

That said : as @JaredPar points out, thread safety issues are not the only reason that a method can throw exceptions. 这就是说 :正如@JaredPar指出的那样,线程安全问题并不是方法抛出异常的唯一原因。 There are a multitude of reasons why a filesystem call might throw an exception (under any circumstances, multithreaded or not), and you need to account for those. 文件系统调用可能会抛出异常(在任何情况下,多线程或非多线程),并且您需要考虑这些原因,这有很多原因。

By saying it is thread safe I (and MSDN) only imply the very literal interpretation of that, meaning "this method does not modify shared program state in a way that could cause invalid state, race conditions, or other adverse effects commonly associated with unsafe multithreaded code" 通过说它是线程安全的I(和MSDN)只暗示对它的字面解释,意思是“此方法不会以可能导致无效状态,竞争条件或通常与不安全相关的其他不利影响的方式修改共享程序状态多线程代码“

To elaborate on @JaredPar's answer, you have a race condition on your hands. 要详细说明@JaredPar的答案,你手上就有竞争条件。 If the first call creates the folder completely, and only then the second call starts, everything will be OK. 如果第一个呼叫完全创建了文件夹,只有第二个呼叫开始,一切都会正常。

however, if the second call reaches the OS while it is still processing the first, the OS might fail the second one dune to locking issues, and you will get an exception. 但是,如果第二个呼叫在仍处理第一个呼叫时到达操作系统,则操作系统可能会使第二个呼叫失败以锁定问题,并且您将获得异常。

It is still thread safe in the sense that you won't get any unpredictable folders created, or no folder at all. 它仍然是线程安全的,因为您不会创建任何不可预测的文件夹,或根本没有文件夹。

To elaborate - while I'm not 100% sure that Windows doesn't have an internal race condition when the same folder is created twice concurrently, I'm pretty certain you won't be able to trash the disk by doing that, or get a deadlock with both creations being stuck to death. 详细说明 - 虽然我并非100%确定Windows在同时创建两个同一文件夹时没有内部竞争条件,但我很确定你无法通过这样做来废弃磁盘,或者两个创作都陷入死亡之中陷入僵局。 One of them will succeed, the other will fail, but the folder will be created. 其中一个会成功,另一个会失败,但会创建文件夹。

So your heuristics, just to be absolutely sure, should be this: 所以你的启发式,只是为了绝对肯定,应该是这样的:

  • Create Directory 创建目录
  • If it fails, wait a random amount of time (say, between 0.2 and 0.5 of a second) and try again. 如果失败,请等待一段随机时间(例如,在0.2到0.5秒之间),然后再试一次。
  • If it fails constantly (say, 3 times in a row), you have another problem at your hands - no permissions to the folder, a full disk, etc.. 如果它经常失败(例如,连续3次),你手上还有另一个问题 - 对文件夹,完整磁盘等没有权限。

    Incidentally, why not create the folder once when the application starts running? 顺便提一下,为什么不在应用程序开始运行时创建文件夹?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM