views:

70

answers:

2

I have, essentially, the same problem as this poster, but in C#: http://stackoverflow.com/questions/1746781/waiting-until-a-file-is-available-for-reading-with-win32

More information: we have code that calls File.Open in one of our projects, that occasionally dies when the file is already opened by another process (EDIT: or thread):

FileStream stream = File.Open(m_fileName, m_mode, m_access);
/* do stream-type-stuff */
stream.Close();

File.Open will throw an IOException (which is currently quietly swallowed somewhere), whose HResult property is 0x80070020 (ERROR_SHARING_VIOLATION). What I would like to do is this:

FileStream stream = null;
while (stream == null) {
    try {
        stream = File.Open(m_fileName, m_mode, m_access, FileShare.Read);
    } catch (IOException e) {
        const int ERROR_SHARING_VIOLATION = int(0x80070020);
        if (e.HResult != ERROR_SHARING_VIOLATION)
            throw;
        else
            Thread.Sleep(1000);
    }
}
/* do stream-type-stuff */
stream.Close();

However, HResult is a protected member of Exception, and cannot be accessed -- the code does not compile. Is there another way of accessing the HResult, or perhaps, another part of .NET I might use to do what I want?

Oh, one final caveat, and it's a doozy: I'm limited to using Visual Studio 2005 and .NET 2.0.

A: 

Your best bet is using reflection unfortunately. Of course, since you sleep for 1sec between attempts, the performance costs will most likely go unnoticed.

Blindy
+2  A: 

You can call Marshal.GetHRForException() within the catch clause to get the error code. No need for reflection:

using System.Runtime.InteropServices;

if (Marshal.GetHRForException(e) == ERROR_SHARING_VIOLATION)
    ....
hmemcpy
Is this thread-safe? The code above is running in a thread; many threads will be attempting to call `File.Open` simultaneously.
Blair Holloway
I think you meant `System.Runtime.InteropServices`, BTW. :)
Blair Holloway
Never mind. MSDN states: "Any public static (Shared in Visual Basic) members of `[Marshal]` are thread safe. Any instance members are not guaranteed to be thread safe."
Blair Holloway
Aah, great! It's good to know that :)
hmemcpy
Actually, `Marshal.GetExceptionCode()` is wrong, now that I've seen it running. What I actually needed was `Marshal.GetHRForException(e)`. Do you mind updating your answer to accomodate?
Blair Holloway
Done! :) Can I get my 5 pts back? ;p
hmemcpy
Yes. Yes you can.
Blair Holloway