Sign in to follow this  
Followers 0

13 posts in this topic

Posted

Hello, 

 

I have a file copying program and I have a custom class that utilizes a System.IO.FileSteam to copy a file to a destination computer.  For the most part it works quite well.  However I use it to copy to many remote locations.  Some of them have subpar network connections.  Every so often I'll get a server that has a unreliable network connection and it will momentarily drop off the network for a few seconds.  When this happens my FileStream breaks with the exception "The specified network name is no longer available.".  This is expected.

However the problem is after the program has waited 60 seconds it will retry the transfer.  The problem now is it can't even start because I get the error "The process cannot access the file '\\MyServer\c$\MyFile.zip' because it is being used by another process".  I'll continue to get this error indefinitely until I close the program and restart the transfer, then it is able to transfer once again.

It would appear that my source server still has a file handle open when this happens that's preventing the transfer again and closing the program releases it.  I would like to programically release the handle so I can restart the transfer automatically.

 

Here's what I've tried so far:

When the file transfer is started, I grab the FileSteam.SafeFileHandle to a variable.  When I get the above error, I've tried accessing SafeFileHandle.SetHandleAsInvalid(), SafeFileHandle.DangerousRelease() and SafeFileHandle.Close(), but I'll still get the file in use error when I retry.

Share this post


Link to post
Share on other sites

Posted

the .Close() should do it.  Are you sure the .Close() is being run? And that your error isn't skipping the close?

Share this post


Link to post
Share on other sites

Posted

To replicate the problem, I imported my DLL into powershell.  I waited for the problem to occur.  I then grabbed the SafeFileHandle.  I first tried SetFileHandleAsInvalid() then retried.  Then I tried DangerousRelease().  Finally I tried Close(), but at that point I got "Exception calling "Close" with "0" argument(s): "Safe handle has been closed".

 

Also if I just call my handle variable it shows:   IsInvalid:  False, IsClosed:  True

Share this post


Link to post
Share on other sites

Posted

Is the filestream locked? Closing a file that has outstanding locks is undefined according to the documentation.

Share this post


Link to post
Share on other sites

Posted

Is the filestream locked? Closing a file that has outstanding locks is undefined according to the documentation.

 

Some how I never thought of that.  I always assumed that when I received an exception on a FileStream.Write(...) that the filestream was hosed then.  I adjusted my code as follows:

                try
                { m_Dest.Write(m_Buffer, 0, m_CurrentBlockSize); }
                catch (IOException ex)
                {
                    //  added the section below:
                    if (m_Dest.CanWrite)
                    {
                        try
                        { m_Dest.Close(); }
                        catch { }
                    }
                    // end new section
                    HadExceptionWhileCopying(ex, true);
                    return;
                }

So far it worked in my test environment.  Will see if it works in production tomorrow.

Thanks Myles!

Share this post


Link to post
Share on other sites

Posted

edit: Please ignore, misread original post.

Share this post


Link to post
Share on other sites

Posted

^ yeah the filestream may still be valid and be locked. For that matter, it could technically be still not working (in terms of communication), but it could still be marked as locked. I was thinking of calling unlock() when I posted my response. I'm not sure why the above code would work given that canWrite should just give you the state of whether the stream is closed or not and if you call close() on an already closed stream it should work fine.

Share this post


Link to post
Share on other sites

Posted

My above solution worked.

 

I dug through my existing code and it was supposed to call a close on the filestream  in the event of an error but due to a flaw in my logic it never got called.

Share this post


Link to post
Share on other sites

Posted

Is it feasible given the code design to just wrap the filestream in a using() {} block?

Share this post


Link to post
Share on other sites

Posted

My above solution worked.

 

I dug through my existing code and it was supposed to call a close on the filestream  in the event of an error but due to a flaw in my logic it never got called.

I see, that definitely fits the bill for the error you were getting!

Share this post


Link to post
Share on other sites

Posted

Is it feasible given the code design to just wrap the filestream in a using() {} block?

 

"using" is an assurance that Dispose() will be called to free resources. It doesn't necessarily call Close(). try...finally would do that.

Share this post


Link to post
Share on other sites

Posted

"using" is an assurance that Dispose() will be called to free resources. It doesn't necessarily call Close(). try...finally would do that.

Yes it does. http://stackoverflow.com/questions/911408/does-stream-dispose-always-call-stream-close-and-stream-flush

 

In general, if an object implements Dispose() then you can expect that calling that is enough to clean it up properly, whatever the state it was in.

 

Also, using actually expands to try-finally so it's strictly equivalent, if all you're doing in the finally clause is to call Dispose().

1 person likes this

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.