В моем приложении я создаю отчеты. Отчеты создаются работами, которые выполняются параллельно. Отчеты должны храниться в уникальных каталогах.Synclock для создания уникальных каталогов в многопоточной среде
Это мое понимание, что код в блоке SyncLock
может быть вызван только по одному потоку за раз. Поэтому я придумал следующий код для генерации уникального пути от текущей даты и времени и счетчика:
Edit: 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# очень приветствуются.
отлична от нуля вероятность того, что «DirectoryLock» должен быть 'Shared'. Мы не можем видеть из фрагмента, будут ли потоки создавать новый объект класса, частью которого является этот код. В этом случае DirectoryLock ничего не блокирует, каждый поток имеет свою собственную копию члена. Имейте в виду, что запуск такого кода более чем в одном потоке очень вреден. У вас есть только один диск, он не любит, когда его управляют несколькими потоками. Конечный результат может быть * lot * медленнее, в котором доминируют временные затраты времени на поиск диска. –
Благодарим вас за комментарий. Создание отчета является частью всего процесса (получение задания, оценка данных, создание отчета, сохранение результатов). Отдельные задачи выполняются один за другим на одно задание. Но поскольку создание отчета не является узким местом, полезно параллельно выполнять несколько заданий. У меня есть только один экземпляр класса ReportCreator, который используется всеми заданиями. Я попытаюсь создать простое примерное приложение для репликации поведения. – Jens
Вы можете просто использовать «Guid» для имени папки, и тогда синхронизация не потребуется. – jmcilhinney