开发者

File.Copy FileNotFoundException reported randomly when it's never true

The code is v开发者_运维知识库ery simple.

If File.Exists(strFileMovingTo) Then File.Delete(strFileMovingTo)
If File.Exists(strFileMovingTo) Then
    Call SendEmail(Globals.EmailInternetTeam, "dev-sql@fad.co.uk", "Display Jpg Problem", "The file " & strFileMovingTo & " cannot be removed by the file mover(to allow a new file to be moved over)")
    Return False
Else
    If File.Exists(strFileMovingFrom) Then
        File.Copy(strFileMovingFrom, strFileMovingTo, True)
        If File.Exists(strFileMovingTo) = False Then
            ''tried to copy file over but must have failed ... send email
            Call SendEmail(Globals.EmailInternetTeam, "dev-sql@friday-ad.co.uk", "Display Jpg Problem", "The file cannot be moved by the file mover from " & strFileMovingFrom & " to " & strFileMovingTo & ". Please have a look at why.")
            Return False
        Else
            Return True
        End If
    End If
    Return False
    ''make sure this file exists on fad dev
End If

However a FileNotFoundException exception is thrown during File.Copy even though its wrapped in a If File.Exists ... End If to check its existance.

The great thing is if you run this through the debugger it nearly always works, when released as an app it almost never works.

Scarily the file always exists.

Anyone know what's going on?


There's probably something else deleting the file and there's a race condition between the call to File.Exists and File.Copy.


I agree with Dave's answer that this looks like a timing issue. Also, if a file can't be deleted for any reason then usually File.Delete will throw an exception. Perhaps you should be catching that instead and reworking your logic.


There is many race condition, you shouldn't blindly rely on File.Exists for other file operations. Anybody can delete or add a file with the same name between two function calls.

If File.Exists(strFileMovingFrom) Then
    // AT THIS TIME, another thread or another process might run
    // the equivalent to **File.Delete(strFileMovingFrom)**
    File.Copy(strFileMovingFrom, strFileMovingTo, True) //Can throw!


The fact that it works in debug tells me it's a timing problem. You're not waiting long enough for the deletes or other file system changes to happen.

Build in a wait of one to two seconds after making file system changes.

UPDATE:

How about this: Create a shared dictionary of file moves you want to perform and use a FileSystemWatcher to carry out the copy action.

If File.Exists(strFileMovingTo) Then File.Delete(strFileMovingTo)
        Thread.Sleep(1000) --Add wait
        If File.Exists(strFileMovingTo) Then
            Call SendEmail(Globals.EmailInternetTeam, "dev-sql@fad.co.uk", "Display Jpg Problem", "The file " & strFileMovingTo & " cannot be removed by the file mover(to allow a new file to be moved over)")
            Return False
        Else
            If File.Exists(strFileMovingFrom) Then
                File.Copy(strFileMovingFrom, strFileMovingTo, True)
                Thread.Sleep(1000) --Add wait
                If File.Exists(strFileMovingTo) = False Then
                    'tried to copy file over but must have failed ... send email
                    Call SendEmail(Globals.EmailInternetTeam, "dev-sql@friday-ad.co.uk", "Display Jpg Problem", "The file cannot be moved by the file mover from " & strFileMovingFrom & " to " & strFileMovingTo & ". Please have a look at why.")
                    Return False
                Else
                    Return True
                End If
            End If
            Return False
            'make sure this file exists on fad dev
        End If


When working with some of file functions of Windows API, which also should be true for .NET one should always be aware about asynchronous nature of file system functions. Asynchronous, means that there is a non-zero, unpredictable, non-guaranteed time between you call to API affecting file system and next successful call to the same API related to the file or directory.

In non-transactional APIs it is common mistake to call something like "create file" then immediatelly try to "findFirst" and fail. Just treat the file system as messaging system with unpredictable delays and develop sort of "protocol" with repetitive polling, sleeps and timeouts or event notifications and callbacks.

However since introduction of Vista there is a different set of guarantees and expectations when applications can use so named "transactional" file API.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜