用于在多线程环境中创建唯一目录的同步锁

本文关键字:同步 唯一 创建 多线程 环境 用于 | 更新日期: 2023-09-27 18:25:29

在我的应用程序中,我正在创建报告。这些报告是由并行运行的作业创建的。报告需要存储在唯一的目录中。

我的理解是,SyncLock块中的代码一次只能由一个线程调用。因此,我想出了以下代码,用于从当前日期和时间以及计数器生成一个唯一的路径:

编辑:DirectoryLock定义为Private DirectoryLock As Object = New Object

'Create a non existant path
Dim ID As String 'Unique ID, that is added to the path
Dim RandomReportName As String 'The resulting directory name
SyncLock DirectoryLock 'Lock the creation of the directory, to avoid the same names
    Dim number As Integer = 0
    Do
        number += 1
        ID = Format(number, "000") 'Create ID from a counter
        RandomReportName = "Report_" & Format(Date.Now, "yyyy_MM_dd-HH_mm_ss.fff") & "_(" & ID & ")" 'Generate the path
        opts.OutputPath = IO.Path.Combine(opts.OutputPath, RandomReportName)
    Loop Until IO.Directory.Exists(opts.OutputPath) = False 'Increase the counter, until a non existant path is found
    IO.Directory.CreateDirectory(opts.OutputPath) 'Create the directory in the synclock, so other threads will need to find a new name (higher counter)
End SyncLock 'Free the code

据我所知,这应该是可行的。然而,当我一次并行运行10个作业时,经常会出现多个线程获得相同路径名的情况,我不明白为什么。

我错过了什么(因为肯定有什么:-)?如何避免这样的问题?

非常欢迎使用VB.NET或C#的答案。

用于在多线程环境中创建唯一目录的同步锁

我在完全错误的一端搜索错误。

我以为锁不起作用,但简单的错误是

opts.OutputPath = IO.Path.Combine(opts.OutputPath, RandomReportName)

我重用相同的变量进行串联。因此,在进一步的循环迭代中,新的RandomReportName将添加到现有的RandomReport中。

当然,解决方案是使用临时变量

'Create a non existant path
Dim ID As String
Dim RandomReportName As String
Dim ResultPath As String = "" 'Stores the unique path name
SyncLock DirectoryLock
    Dim number As Integer = 0
    Do
        number += 1
        ID = Format(number, "000") 'Create ID from a counter
        RandomReportName = "Report_" & Format(Date.Now, "yyyy_MM_dd-HH_mm_ss.fff") & "_(" & ID & ")" 'Generate the path
        ResultPath = IO.Path.Combine(opts.OutputPath, RandomReportName) 'Assign the result path with the combined base path and unique name
    Loop Until IO.Directory.Exists(ResultPath) = False
    IO.Directory.CreateDirectory(ResultPath)
    opts.OutputPath = ResultPath 'Store the temporary variable for further use
End SyncLock 'Free the code