one my application features is tod download files from our ftp server. And of course this feature reqiures to cancel this operation (Cancel Downloading).
Now, my Download Function is as follows:
try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri('ftp://' + uri + '/' + fileName)); reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.UsePassive = true; response = (FtpWebResponse)reqFTP.GetResponse(); ftpStream = response.GetResponseStream(); _isItOutputStream = true; string dataLengthString = response.Headers['Content-Length']; int dataLength = 0; if (dataLengthString != null) { dataLength = Convert.ToInt32(dataLengthString); } long cl = response.ContentLength; int bufferSize = 4048; int readCount; byte[] buffer = new byte[bufferSize]; readCount = ftpStream.Read(buffer, 0, bufferSize); outputStream = new FileStream(filePath + '\\' + fileName, FileMode.Create); bool first = true; while (readCount > 0) { outputStream.Write(buffer, 0, readCount); _actualDownloaded += readCount; if (this.InvokeRequired) { ProgressBarDel _progressDel = new ProgressBarDel(ProgressBar); this.Invoke(_progressDel, new object[] { _actualDownloaded, first }); } first = false; readCount = ftpStream.Read(buffer, 0, bufferSize); } ftpStream.Close(); outputStream.Close(); response.Close(); _isItOutputStream = false; return true; } catch (Exception ee) { _downloadException = ee.Message; if (ftpStream != null && outputStream!=null ) if (ftpStream.CanRead && outputStream.CanWrite) { ftpStream.Close(); outputStream.Close(); } if (response != null) response.Close(); return false; }
Now as you can see in Catch Block you can see that i’m trying to interrupt this connection when the user clicks on Cancel button.
- Canceling Operation Scenario:
1) Cancel button was clicked.
2) Call Function ‘DoSomeWorx()’
3) in ‘DoSomeWorx()’ do:
if (_isItOutputStream)// where here i'm trying to check if it's downloading { ftpStream.Close(); outputStream.Close(); response.Close(); } if (_startCopy)// check if copying to phone { IsCancelled(); } _btnDownload2PhoneThread.Abort(); // actually this operation does what i did before but for some resoans it does this but it takes time... _btnDownload2PhoneThread.Join();
The Problem is when I reach any of the following statments (ftpStream.Close();outputStream.Close();response.Close();)
it throws an exception ‘File unavailable(e.g file is busy)’
and this exception affects on re-downloading operation where it sees the file busy.
so how to avoid this exception?
I’m assuming that you have a form of some sort, so your performing the download on a thread.
What your probably better off doing is checking a ‘cancel’ flag inside your while loop.
eg.
Then let your method gracefully cancel out.
Secondly you should use a using statement on your streams. That means that if you throw an exception, the finally block will guarantee that your stream gets disposed (which incidentally is why you would be receiving file busy, as the stream hasn’t yet had it’s destructor run, even though your method has completed)