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.
精彩评论