0 votes
by (210 points)

Hi,

My application uses the Rebex SFTP GetFileAsync method to download file updates and then read the file. Sometime in the last year, I upgraded Rebex and now I have started getting "the process cannot access the file XXX because it is being used by another process" errors.

I have checked, and mine is the only process accessing the file.

I am reading the file read-only, with sharing, in a using statement.

My question is - how is the file being written? Is sharing possible? Is the file handle being disposed of properly?

My code already implements a retry mechanism, but this is proving insufficient. This error seems to have appeared at some point over the last 18 months.

Thanks,

Toby

Applies to: Rebex SFTP
by (210 points)
Also - it is the GetFileAsync method which is throwing the exception.  So, the retry mechanism on the read end is working.  

Is there a retry mechanism on the GetFileAsync call?
by (147k points)
GetFileAsync, like GetFile, does not retry the operation on it's own (unlike DowloadAsync/Download, where this is an option). A bit of custom code is needed for that. For details, see https://www.rebex.net/sftp.net/features/single-file-operations.aspx#resume

1 Answer

0 votes
by (147k points)

Hi,

First, please note that "the process cannot access the file XXX because it is being used by another process" error comes from .NET and the wording is misleading. Instead of "being used by another process", is should rather say "being used by another process or by the current process". It's quite easy to open a file without closing it by mistake - a common cause is a call to File.Create(path) without a correspnding Close call.

The GetFileAsync method opens the file for writing by calling new FileStream(localPath, FileMode.Create, FileAccess.Write, FileShare.Read), so if your process (or another process) opened the file for writing without closing it, GetFileAsync will fail.

Also, GetFileAsync always closes the file (in finally block), even if it fails. It's unlikely there would be a bug there, but in order to rule this out, consider using the Stream-based overload of GetFileAsync method instead - open the file for writing yourself by calling the FileStream constructor (as shown above), and close the Stream when the method succeeds or fails. This way, the file will be completely under your control.

by (210 points)
Thanks for the quick reply.

What I really need is to retry the "new FileStream" call as this is where the exception is thrown.  

If I understand correctly, I can do this myself with the method:
GetFileAsync(string remotePath, Stream outputStream)

To handle the stream, I will need to use the non-async 'GetFile' call. ...and them make it async myself.  This is a little bit annoying.  It would be nice if Rebex could handle this complexity internally.  Maybe something for the future?

Thanks Lukas!

Toby
by (147k points)
Actually, Stream-based 'GetFileAsync' is available as well, and if await/async is available on your platform, you could easily use that to achieve what you need.

I'm not sure whether a new option to "wait until a file is creatable or truncatable/writable" would be widely useful, but if more customers express interest in it, we will consider it for one of the next major releases.
by (210 points)
I understand - thanks for the reply.

My 2 cents would be that if the more popular 'download' method has a retry mechanism, then the GetFile should have it as well.  If not, well, then I may need to wrap the download call as well!  :-)

Thanks again,

Toby
by (210 points)
edited by
[Removed, see below.]
by (210 points)
edited by
[Removed, see below.]
by (210 points)
edited by
[Removed]

Apologies.  There were some things I wasn’t understanding, but I think I got it now.
by (147k points)
If you would like any further feedback on this, please let me know!
...