简体   繁体   中英

Why is File.Open so expensive?

I have the following code:

try
{
    string fileName = imageQueue.Dequeue();
    FileStream fileStream = File.Open(
        fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    Bitmap bitmap = new Bitmap(fileStream);
    Image picture = (Image)bitmap;
    pb.Tag = fileName;
    pb.Image = picture;
    return true;
}
catch (Exception ex)
{
    errorCount++;
    //If another PC has this image open it will error
    return false;
}

Because this program is running on 2 PC's accessing the same folder to pick files up it will throw an exception when one has a file open and then move onto the next file in its list.

When I open the application on 2 PC's at the same time the first PC manages to open the image but the second doesn't. I am displaying 4 images at once on screen but doing some debugging shows that the second PC is taking 10.5 seconds to fail at opening 4 files before it finds one it can open.

Why is this so expensive and what can I do to speed it up?

UPDATE: I give it exclusive access because I want the applications to show unique images so PC1 shows image 1,2,3,4 and PC shows 5,6,7,8 because it cant get acccess to 1,2,3,4. I also then free the filestream once I'm done with it and at the last possible moment so it prevents other applications trying to open it.

You are opening the file as FileAccess.ReadWrite (you don't appear to be writing). You tell it that you don't want to share the file, FileShare.None , (so the first PC to get the file wins).

Also, you never close the stream. So the PC that gets the file first holds on to it until the garbage collector closes the stream for you. When you get your stream wrap it in a using block so that the file is closed automatically:

using (FileStream fileStream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
{
    // Do stuff with the filestream
}
// The stream will be closed when the closing brace is passed.

I can't answer definitively, but my best suggestion is that something in the system, either in the .net framework classes or the file system, is implementing a timeout/retry mechanism in case of file sharing failures. This would explain the inordinate delay you report.

After Edit

Since you want them to be locked you might consider rolling a light weight database (sqllite, xml, etc) that you could use to flag a file as "in use". Then in the method you would check to see if it's in use. This will eliminate having to wait for File.Open to timeout when trying to open a locked file.

Original

I guess I should have answered instead of commenting...

try
{
    string fileName = imageQueue.Dequeue();
    using( FileStream fileStream = File.Open( fileName, FileMode.Open, FileAccess.Read, FileShare.Read) )
    {
        Bitmap bitmap = new Bitmap(fileStream);
        Image picture = (Image)bitmap;
        pb.Tag = fileName;
        pb.Image = picture;
    }

    return true;
}
catch (Exception ex)
{
    errorCount++;
    //If another PC has this image open it will error
    return false;
}

Have you tried experimenting with these stream properties? You may be able to minimize the timeout, if nothing else:

http://msdn.microsoft.com/en-us/library/470w48b4.aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM