2012-03-05 62 views
12

我可以安全地尝试从两个不同的线程创建相同的目录,但没有其中一个抛出异常,或遇到其他问题?是C#中的CreateDirectory()线程安全吗?

注意的是,根据MSDN,这是确定调用CreateDirectory()上已经存在的目录,在这种情况下,该方法有望无可奈何。

回答

13

调用本身可以安全地从多个线程中调用。如果你这样做,它不会损坏程序或文件系统状态。

但是不可能以这种方式调用Directory.CreateDirectory以保证它不会抛出异常。文件系统是一个不可预知的野兽,在任何给定的时间内,您可以通过其他程序对其进行更改。这是非常可能的例子来看看下面发生

  • 计划1线程1:调用CreateDirectoryc:\temp\foo并且取得了成功
  • 计划2线程1:从程序1用户
  • 计划1线程删除要c:\temp访问2:呼叫CreateDirectory并且由于没有足够的访问

抛出总之你必须假定Directory.CreateDirectory,还是真的其中涉及文件系统中的任何功能,能够而且将会ŧ相应地进行伸缩和处理。

6

MSDN docs on Directory

任何公共静态此类型的成员(在Visual Basic中的Shared)都是线程安全的。任何实例成员不保证是线程安全的。

因此,由于CreateDirectory是静态的,所以它是线程安全的。

也就是说:正如@JaredPar指出的,线程安全问题不是方法抛出异常的唯一原因。文件系统调用可能会引发异常(在任何情况下,多线程或不)的原因有很多,您需要考虑这些原因。我的(和MSDN)只意味着它的字面解释,意思是“这种方法不会修改共享程序状态,导致无效状态,竞态条件或其他不利影响通常与不安全的多线程代码相关联“

+0

这并没有解决问题,但它是否会抛出一个或两个线程 – JaredPar 2012-03-05 19:44:33

+0

真的 - 我相信你的答案覆盖更好(我upvoted btw)。我会修改我的答案。 – 2012-03-05 19:55:33

4

为了阐述@ JaredPar的答案,你的手上有一个竞争条件。如果第一个电话完全创建文件夹,只有第二个电话开始,一切都会好的。但是,如果第二次调用在操作系统仍在处理第一个调用时到达操作系统,则操作系统可能会失败,第二个沙丘会出现锁定问题,您将得到一个异常。

它仍然是线程安全的,因为您不会得到任何不可预知的文件夹创建,或根本没有文件夹。

要阐述 - 而我不是100%肯定,Windows不具备当同一文件夹中创建同时两次内部竞争,我敢肯定,你将无法通过向垃圾盘这样做,或者两个创作都陷入死亡而陷入僵局。其中一人会成功,对方会失败,但该文件夹将被创建。

所以,你的启发,只是绝对肯定,应该是这样的:

  • 创建目录
  • 如果失败,等待一段随机时间(比如0.2秒到0.5之间)然后再试一次。
  • 如果它不断失败(比如,连续3次),你必须在你的手中了另一个问题 - 没有权限的文件夹,一个完整的磁盘等。

    顺便说一下,为什么无法创建文件夹一旦应用程序开始运行?

+0

你确定吗?我的目的是有几个不同的线程创建(独立的),在相同的日志文件的目录,如果需要创建它。假设你是正确的,并创建文件夹不是一个原子操作,我必须使用(例如)一个锁来进行同步。什么是关于CreateDirectory()的“线程安全”呢? – bavaza 2012-03-06 07:38:31

+0

我会详细说明。 – zmbq 2012-03-06 07:40:30

+0

谢谢。我认为这可能是我看到的行为。 – 2016-08-05 17:19:55