我正在创建一个从数据库获取文件数据的程序。要求文件在存在“IMAGE_00001.JPG”、“IMAGE_00002.JPG”、.
由于性能问题,我将并行加载数据,但创建文件时会遇到问题。
For i As Long = 1 To maxSeqNr
DIDir = New DirectoryInfo(currDir)
If DIDir.GetFiles(currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), Len(maxSeqNr.ToString)) & ".*", SearchOption.TopDirectoryOnly).Length = 0 Then
sRetValue = currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), Len(maxSeqNr.ToString)) & currFileExtention
Dim oSW As StreamWriter
oSW = New StreamWriter(currDir & sRetValue)
oSW.WriteLine("")
oSW.Close()
oSW.Dispose()
oSW = Nothing
Exit For
End If
Next问题是,有时两个线程运行的代码行相同。我添加了日志,我发现了以下内容:
Check for 'IMAGE_00001.JPG' ; Directory: ''
Check for 'IMAGE_00001.JPG' ; Directory: ''
Check for 'IMAGE_00002.JPG' ; Directory: 'IMAGE_00001.JPG'
Check for 'IMAGE_00003.JPG' ; Directory: 'IMAGE_00001.JPG,IMAGE_00002.JPG'是否有可能在执行Exists语句之前“锁定”工作目录。在我创建文件后“释放”?其他线程应该等待,直到它们能够“锁定”目录。
发布于 2013-08-29 14:15:21
您应该生成要使用的名称,然后尝试使用该名称创建FileStream对象。使用合适的构造函数接受FileMode参数(例如这一个)并指定CreateNew。
如果抛出一个IOException并生成一个新名称,则捕获它。
否则,你所面对的是一种典型的种族。这取决于您是选择组合原始策略(检查是否存在,然后尝试打开文件),还是只尝试创建文件并期望异常。
一旦您成功地打开了FileStream,就可以将它传递给接受Stream参数的StreamWriter构造函数,然后从那里开始。
发布于 2013-08-29 14:12:03
我会使用syn / lock策略:当线程想要写入文件并停止所有其他线程时锁定,直到完成为止,然后释放锁。http://msdn.microsoft.com/de-de/library/vstudio/ms173179.aspx
或者,使用一个非阻塞整数作为计数器,因此它将保证一个唯一的文件,但它可能会搞乱您的“编号”要求。http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx
发布于 2013-08-29 14:29:02
如果只需通过IMG_00000.jpg IMG_XXXXX.jpg生成空白文件,则可以使用Parallel.For循环来创建不存在的文件。这将确保两个数字不被两个不同的线程检查,而是在线程之间划分出数字。
虽然我不知道这实际上会更快,特别是如果您必须在目录中搜索一个扩展名与图像名称匹配的文件:
Dim width = Len(maxSeqNr.ToString)
Dim DIDir = New DirectoryInfo(currDir)
Parallel.For(1L, maxSeqNr, Sub(i)
Dim pattern = currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), Len(maxSeqNr.ToString)) & ".*"
If Not DDir.EnumerateFiles(pattern, SearchOption.TopDirectoryOnly).Any Then
Dim fn = currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), width) & currFileExtention
File.Create(fn).Close
End If
End Sub)如果您正在搜索的文件夹很小,这可能会更好(假设您实际上关心与模式匹配的任何文件名):
' My VB.Net is horrible
Dim width = Len(maxSeqNr.ToString)
Dim files = Directory.GetFiles(currDir)
Parallel.For(1L, maxSeqNr, Sub(i)
Dim pattern = currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), Len(maxSeqNr.ToString))
' consider case-insenstive matching
If Not files.Any(Function(fn) Path.GetFileNameWithoutExtension(fn) = pattern) Then
Dim fn = currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), width) & currFileExtention
File.Create(fn).Close
End If
End Sub)或者,如果您真正需要的是只在不存在的情况下创建一个文件,那么您只需继续访问所有文件:
Parallel.For(1L, maxSeqNr, Sub(i)
Dim fn = currFilePrefix & Microsoft.VisualBasic.Right(maxSeqNrLeadingZeros & CStr(i), width) & currFileExtention
File.Open(fn, FileMode.OpenOrCreate).Close
End Sub)https://stackoverflow.com/questions/18512228
复制相似问题