We are using the .Net FtpWebRequest class to transfer files in our application and it seems that we are experiencing problems with an indefinite wait, we think this is potentially occurring somewhere inside the .Net library code.
We are using the async versions of the methods and our (simplified) code looks as follows:
async Task DoTransfer(int id, CancellationToken cTkn)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(targetAddress);
request.UsePassive = true;
request.KeepAlive = true;
request.Timeout = 300000; // 5 minutes
request.Method = WebRequestMethods.Ftp.UploadFile;
using (var stream = await request.GetRequestStreamAsync())
{
...create a byte buffer of the file here
cTkn.ThrowIfCancellationRequested();
await stream.WriteAsync(buffer, 0, buffer.Length, cTkn);
}
using (var response = (FtpWebResponse)await request.GetResponseAsync())
{
cTkn.ThrowIfCancellationRequested();
...do something with status code
}
}
catch (OperationCanceledException)
{
...logging
}
catch (Exception ex)
{
...logging
}
finally
{
...code to remove this task from a concurrent dictionary using the 'id' param
}
}
When we create the task initially, we add it to a concurrent dictionary for monitoring (random ID generated). The task then removes itself from this dictionary once it is complete (in the finally block). The problem we are having is that the task never removes itself indicating that the finally block has never been reached.
The cancellation token we use is a linked token from a "master" cancellation token and a new timeout token created just before the task is launched (set to 5 minutes).
We can't isolate which method is hanging as this app processes around 100 files/minute and the issue only occurs very rarely so the log files are just too large to read manually.
The app may start up to 24 of these DoTransfer tasks at any one time (often connecting to the same FTP server).
Does anyone know of any issues with either the GetRequestStreamAsync() or GetResponseAsync() methods that may cause them to never return when run in parallel like this?
Or have any suggestions on how to terminate long running tasks (as we can't pass the cancellation token to either of those two FtpWebRequest methods)?