I am trying this TFTP client for my application as Client. However, there is a bug somewhere when sometimes my program which is trying to read the stream throwing exception that the stream is already closed. After some digging in source code I found that in TftpTransfer.cs
there is Dispose method, which sometimes called and then exception is thrown.
I can't find why sometimes Dispose method is called before I use the stream(after TFTP transfer is done) and how to address it.
Following is the code and exception occurs on setting position to 0.
private static AutoResetEvent TransferFinishedEvent = new AutoResetEvent(false);
....
var client = new TftpClient("192.168.0.1");
var transfer = client.Download("00-02.conf");
transfer.OnFinished += new TftpEventHandler(transfer_OnFinshed);
transfer.OnError += new TftpErrorHandler(transfer_OnError);
Stream stream = new MemoryStream();
transfer.Start(stream);
TransferFinishedEvent.WaitOne();
stream.Position = 0;
var sr = new StreamReader(stream);
var myStr = sr.ReadToEnd();
Console.WriteLine(myStr);
...
static void transfer_OnError(ITftpTransfer transfer, TftpTransferError error)
{
Console.WriteLine("Transfer failed: " + error);
TransferFinishedEvent.Set();
}
static void transfer_OnFinshed(ITftpTransfer transfer)
{
Console.WriteLine("Transfer succeeded.");
TransferFinishedEvent.Set();
}
UPD: Workaround which didn't work yet
MemoryStream stream = new MemoryStream();
var sr = new StreamReader(new MemoryStream(stream.GetBuffer()));
transfer.Start(stream);
TransferFinishedEvent.WaitOne();
Console.WriteLine(sr.ReadToEnd());
sr
is always pointing to end of stream and it's empty.
UPD2: One thing which maybe worth to mention. Exception cannot access a closed Stream happens only on Windows XP box (.NET 3.5 which I have to stick to). I have tried on Windows 7 and even though sometimes I see the stream inside framework disposed, I don't have exception. Again, on Windows XP exception happens randomly. Approximately every 3 calls to my app throwing exception.
The stream appears to be closed by design in the library when it gets to the end of the download.
//Was that the last block of data?
if (command.Bytes.Length < Context.BlockSize)
{
Context.RaiseOnFinished();
Context.SetState(new Closed());
}
Where the Closed state just calls Dispose()
on the instance of TftpTransfer
(which in turn closes the stream).
I'd argue that's maybe a bug in the library - it doesn't own the stream so it shouldn't be closing it but you're stuck with that for now.
The simplest solution is to create a new memory stream to read the bytes captured like this::
var sr = new StreamReader(new MemoryStream(stream.GetBuffer());