This project is read-only.

SftpClient.BeginUploadFile and uncalled delegate?

May 10, 2011 at 6:28 PM

I have a problem with SftpClient's BeginUploadFile method and EndUploadFile, my delegate simply isnt called...

In SftpCommand.cs, I assume that when a command is finished, it should end up in EndExecute, and call this._callback(result) ?

I tried debugging, but no luck so far.

May 10, 2011 at 9:21 PM
Edited May 10, 2011 at 9:22 PM

What happens is the callback is called on new thread.

Try this example and let me know what you get.

            using (var sftpClient = new SftpClient(connectionInfo))
            {
                sftpClient.Connect();
                EventWaitHandle wait = new AutoResetEvent(false);
                Console.WriteLine("\nUpload started.");
                var asynch = sftpClient.BeginUploadFile(File.OpenRead(@"C:\Test\small.txt"), "/home/oleg/test1.txt", 
                    delegate(IAsyncResult ar)
                    {
                        Console.Write("\nCallback called.");
                        wait.Set();
                    }, 
                    null);

                var sftpASynch = asynch as SftpAsyncResult;
                while (!sftpASynch.IsCompleted)
                {
                    Console.Write(string.Format("\rUploaded {0} bytes ", sftpASynch.UploadedBytes));
                    Thread.Sleep(100);
                }
                Console.Write(string.Format("\rUploaded {0} bytes ", sftpASynch.UploadedBytes));
                sftpClient.EndUploadFile(asynch);
                wait.WaitOne();
            }
            Console.Write("\nUpload completed.");
            Console.ReadKey();

In my case I am getting this output:

Upload started.
Uploaded 102400 bytes
Callback called.
Upload completed.

Also, if you want to see this event being fired, it happens in this line : SftpCommand.cs line 63.

Let me know if it helps,

Thanks,

Oleg

May 11, 2011 at 8:59 AM

I am at work, but this code appears to work, but I changed the SftpClient constructor to the constructor accepting (host, port, username, password).

I tested a 40 byte file, this worked and produces the expected result.

I am now testing with "Windows_Win7.7600.16385.090713-1255.X86FRE.Symbols.msi" 323 MB (338 847 744 byte). But given that the previous test worked, I expect this test to work, unless it uncovers additional issues.

I will test your code in my project when I get home.

Unlike your code, in my form, I have

private SftpClient ftp;
private SshClient ssh;

At the moment I only use ftp. Methods on ftp are almost always called from  a UI thread (if it matters), but I use Application.DoEvents() and Begin* to avoid UI blocking. Its just a rough experiment, so extreme quality is lacking here.

May 11, 2011 at 9:25 AM

Upload started.
Uploaded 338847744 bytes
Callback called.
Upload completed.

May 11, 2011 at 2:28 PM

2Oleg: Upload started.
2Oleg: Uploaded 1344512 bytes 
2Oleg: Callback called.
2Oleg: Upload completed.

Modified the code abit (using Debug.WriteLine instead of Console.WriteLine, and it works, so I am doing something wrong.

	using (var sftpClient = new SftpClient(this.ftp.ConnectionInfo))
			{
				sftpClient.Connect();
				System.Threading.EventWaitHandle wait = new System.Threading.AutoResetEvent(false);
				Debug.WriteLine("Upload started.","2Oleg");
				var asynch = sftpClient.BeginUploadFile(File.OpenRead(file.FileInfo.FullName), this.destination + "/" + file.FileInfo.Name,
					delegate(IAsyncResult ar)
					{
						Debug.WriteLine("Callback called.", "2Oleg");
						wait.Set();
					},
					null);

				var sftpASynch = asynch as SftpAsyncResult;
				while (!sftpASynch.IsCompleted)
				{
					Debug.WriteLine(string.Format("Uploaded {0} bytes ", sftpASynch.UploadedBytes), "2Oleg");
					System.Threading.Thread.Sleep(100);
				}
				Debug.WriteLine(string.Format("Uploaded {0} bytes ", sftpASynch.UploadedBytes), "2Oleg");
				sftpClient.EndUploadFile(asynch);
				wait.WaitOne();
			}
			Debug.WriteLine("Upload completed.", "2Oleg");

 

May 11, 2011 at 2:50 PM

So, I've played around abit...

When the while (!sftpASynch.IsCompleted)-code is present, it works, the callback and upload works, but if I comment out from var sftpASync... to wait.WaitOne(); (and in the delegate, it doesnt work. The Thread.Sleep doesnt affect it when uncommenting it..

But sometimes it doesnt even upload the file, and its a zero-byte file, it just blocking on Session.Read() after Upload started comes out. There are two threads blocking there.