关于例外:如何摆脱访问同一文件的2种方法之间的等待时间?

How can I get rid of wait time between 2 methods that access the same file?

我有以下一段VBSCript代码,可以在纯文本文件中找到一个部分(strSection)和该部分中的项目(strItem)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Do While Not myINIFile.AtEndOfStream
  sl_Sleep(100)
  s = myINIFile.ReadLine <--- **This is the line that rises the exception**
  If s = strSection Then
    'Find the correct line
    Do While Not myINIFile.AtEndOfStream
      s = myINIFile.ReadLine
      If InStr(s, strItem)>0 Then
        Exit Do
      End if              
    Loop            
    Exit Do
  End if              
Loop

看来,如果我不输入Sleep(100)(毫秒)(或使用较低的值,例如20或50),我最终会得到一个异常,指出"该进程无法访问文件,因为另一个进程已锁定了一部分文件"。

我认为在AtEndOfStream尚未完成时,正在调用Do While中的条件是ReadLine方法。但是,对于每条线使用100毫秒会将进程减慢到无法接受的速度。

这是真正发生的事情还是其他地方的问题?
有什么我可以做的事情,以防止该过程被锁定或等待更多时间(直到它被释放)(只有在锁定后才不会引发异常)?

编辑:此代码循环遍历如下所示的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Section1]    
param1 = 100    
param2 = 200    
param3 = 300    

[Section2]    
param1 = 1000    
param2 = 2000    
param3 = 3000

[Section3]    
param1 = 1
param2 = 2
param3 = 5
param4 = 10
param5 = 20

代码应该遍历文件,直到找到[SectionX]行(strSection),然后继续读取行,直到找到" paramx"行(strItem)。然后将该行保留在" s"中,并在以后进行处理。


在这里,此代码将执行循环。您遇到的问题是对同一流重新使用readline,并且读取了EOF之后(和/或)创建了文件锁争用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Const TristateFalse = 0
Const ForReading = 1

strINIfile ="c:\\scripts\\testconfig.ini"
strSection ="[Section2]"
strItem ="param3"

Set objFSO = WScript.CreateObject("Scripting.Filesystemobject")
Set objINIstream = objFSO.OpenTextFile(strINIfile, ForReading, False, TristateFalse)

boolCheckSection = False

Do While Not objINIstream.AtEndOfStream
    strLine = Trim(objINIstream.ReadLine)

    ' Determine if we're in the section, set boolcheck if so
    If InStr(UCase(strLine),UCase(strSection)) Then    
        boolCheckSection = True    
    ElseIf InStr(UCase(strLine),"[") Then  
        boolCheckSection = False
    End If

    ' If so, read the proper value and store in variable
    If boolCheckSection Then
        If InStr(UCase(strLine), UCase(strItem)) Then
            tmpParam = Split(strLine,"=")
            strParamValue = Trim(tmpParam(1))
            Exit Do ' exit loop with set variable
        End If      
    End If

Loop

WScript.Echo strParamValue


您发布的代码非常适合我。我没有例外...

您在使用发布的代码时是否正在其他任何地方访问文件?

您是否尝试读取整个文件,然后解析字符串?参见http://www.motobit.com/tips/detpg_asp-vbs-read-write-ini-files/


感谢大家的答复。查看您提出的代码并进行研究,使我意识到我自己的代码没有任何错误(即使有2个while循环,它也正确退出了它们)。在尝试了您提出的代码之后,我仍然发现它在我的测试用例中是随机断言的,并且在考虑了它之后,我意识到我正在测试的主应用程序仍然访问了该文件(尽管我不知道它是做什么的,但这是另外一回事)。

我发现的解决方案是我们在手动测试时始终建议的解决方案。复制原件并进行复印。

此外,感谢您提出的代码,它们给了我不同的angular,以改善我的代码设计和可读性。


函数ReadIni(myFilePath,mySection,myKey)
'此函数返回从INI文件读取的值
'
的参数:
'myFilePath [string] INI文件的(路径和)文件名
'mySection [string] INI文件中要搜索的部分
'myKey [string]要返回其值的键
'
返回:
'指定部分中指定键的[string]值
'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Const ForReading   = 1
Const ForWriting   = 2
Const ForAppending = 8

Dim intEqualPos
Dim objFSO, objIniFile
Dim strFilePath, strKey, strLeftString, strLine, strSection

Set objFSO = CreateObject("Scripting.FileSystemObject" )

ReadIni     =""
strFilePath = Trim( myFilePath )
strSection  = Trim( mySection )
strKey      = Trim( myKey )

If objFSO.FileExists( strFilePath ) Then
    Set objIniFile = objFSO.OpenTextFile( strFilePath, ForReading, False )
    Do While objIniFile.AtEndOfStream = False
        strLine = Trim( objIniFile.ReadLine )

        ' Check if section is found in the current line
        If LCase( strLine ) ="[" & LCase( strSection ) &"]" Then
            strLine = Trim( objIniFile.ReadLine )

            ' Parse lines until the next section is reached
            Do While Left( strLine, 1 ) <>"["
                ' Find position of equal sign in the line
                intEqualPos = InStr( 1, strLine,"=", 1 )
                If intEqualPos > 0 Then
                    strLeftString = Trim( Left( strLine, intEqualPos - 1 ) )
                    ' Check if item is found in the current line
                    If LCase( strLeftString ) = LCase( strKey ) Then
                        ReadIni = Trim( Mid( strLine, intEqualPos + 1 ) )
                        ' In case the item exists but value is blank
                        If ReadIni ="" Then
                            ReadIni =""
                        End If
                        ' Abort loop when item is found
                        Exit Do
                    End If
                End If

                ' Abort if the end of the INI file is reached
                If objIniFile.AtEndOfStream Then Exit Do

                ' Continue with next line
                strLine = Trim( objIniFile.ReadLine )
            Loop
        Exit Do
        End If
    Loop
    objIniFile.Close
Else
    WScript.Echo strFilePath &" doesn't exists. Exiting..."
    Wscript.Quit 1
End If

结束功能