I am very confused about GetFileAsync when using SFtp.
If two tasks are executed and 'A' task is canceled and 'B' task is in a block state(writing is blocked for other io),
the 'A' task Wait() call is not returned until 'B' task is released.
I do not seem to understand the Async function.
In the example below, I would like you to help me understand what I do not understand.
(BeginGetFile, EndGetFile is same issue. EndGetFile is blocked)
class Program
{
    static void Main(string[] args)
    {
        Task task1 = null;
        Task task2 = null;
        Sftp sftp = Connect();
        if (sftp == null)
        {
            Console.ReadKey();
            return;
        }
        try
        {
            string filename = $"/home/011.jpg";
            string asyncState = filename;
            task1 = sftp.GetFileAsync(filename, new WaitStream(), 0, 512 * 1024, asyncState);
            Console.WriteLine($"{DateTime.Now.ToString()} Wait Task Created");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"{DateTime.Now.ToString()} Wait Task Created Error : {ex.Message}");
        }
        try
        {
            string filename = $"/home/019.jpg";
            string asyncState = filename;
            task2 = sftp.GetFileAsync(filename, new NoWaitStream(), 0, 512 * 1024, asyncState);
            Console.WriteLine($"{DateTime.Now.ToString()} NoWait Task Created");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"{DateTime.Now.ToString()} NoWait Task Created Error : {ex.Message}");
        }
        try
        {
            sftp.AbortTransfer(task2.AsyncState);
            Console.WriteLine($"{DateTime.Now.ToString()} NoWait Task Aborted");
            task2.Wait();
            Console.WriteLine($"{DateTime.Now.ToString()} NoWait Task Ended");
        }
        catch (Exception ex)
        {
            if (ex.InnerException != null)
                Console.WriteLine($"{DateTime.Now.ToString()} NoWait Task Wait Error : {ex.InnerException.Message}");
            else
                Console.WriteLine($"{DateTime.Now.ToString()} NoWait Task Wait Error : {ex.Message}");
        }
        try
        {
            sftp.AbortTransfer(task1.AsyncState);
            Console.WriteLine($"{DateTime.Now.ToString()} Wait Task Aborted");
            task1.Wait();
            Console.WriteLine($"{DateTime.Now.ToString()} Wait Task Ended");
        }
        catch (Exception ex)
        {
            if (ex.InnerException != null)
                Console.WriteLine($"{DateTime.Now.ToString()} Wait Task Wait Error : {ex.InnerException.Message}");
            else
                Console.WriteLine($"{DateTime.Now.ToString()} Wait Task Wait Error : {ex.Message}");
        }
        Console.WriteLine($"{DateTime.Now.ToString()} Finished");
        Console.ReadKey();
    }
    static Sftp Connect()
    {
        try
        {
            Sftp sftp = new Sftp();
            sftp.MaxDownloadSpeed = 0;
            sftp.MaxUploadSpeed = 0;
            sftp.Settings.UseLargeBuffers = true;
            sftp.Encoding = Encoding.UTF8;
            sftp.Connect("192.168.0.8", 22);
            sftp.Login("test", "test");
            return sftp;
        }
        catch(Exception ex)
        {
            Console.WriteLine($"Connect Failed : " + ex.Message);
            return null;
        }
    }
    private class NoWaitStream : Stream
    {
        public override bool CanRead
        {
            get { return false; }
        }
        public override bool CanSeek
        {
            get { return false; }
        }
        public override bool CanWrite
        {
            get { return true; }
        }
        public override void Flush()
        {
        }
        public override long Length
        {
            get { throw new NotSupportedException(); }
        }
        public override long Position
        {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }
        public override void Write(byte[] buffer, int offset, int count)
        {
        }
        public override void Close()
        {
            base.Close();
        }
    }
    private class WaitStream : Stream
    {
        public override bool CanRead
        {
            get { return false; }
        }
        public override bool CanSeek
        {
            get { return false; }
        }
        public override bool CanWrite
        {
            get { return true; }
        }
        public override void Flush()
        {
        }
        public override long Length
        {
            get { throw new NotSupportedException(); }
        }
        public override long Position
        {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }
        public override void Write(byte[] buffer, int offset, int count)
        {
            Thread.Sleep(10000);
        }
        public override void Close()
        {
            base.Close();
        }
    }
}
In my case, GetDownloadStream / GetUploadStream works very well for my processing. However, performance is unsatisfactory (1 Gbps Wired Connection).
The GetDownloadStream / GetUploadStream function uses Ping / Pong Communication, so performance does not work properly.
I would like to ask if you can create GetDownloadStream / GetUploadStream using asynchronous communication like GetFile/PutFile.
For example :
Stream stream = sftp.GetBufferdDownloadStream();
...
// Cancel Transfer
stream.Close(); // don't send unsent acks
// Normal Close
stream.Flush(); // send all unsent acks
stream.Close();
Thank you.