diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj
index 2af20911c..8d1ccc18e 100644
--- a/src/Renci.SshNet/Renci.SshNet.csproj
+++ b/src/Renci.SshNet/Renci.SshNet.csproj
@@ -33,7 +33,7 @@
- FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA
+ NET35;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA
FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SETSOCKETOPTION;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA
diff --git a/src/Renci.SshNet/SftpClientExtensions.cs b/src/Renci.SshNet/SftpClientExtensions.cs
new file mode 100644
index 000000000..fb98a7d7d
--- /dev/null
+++ b/src/Renci.SshNet/SftpClientExtensions.cs
@@ -0,0 +1,181 @@
+#if !NET35
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+ ///
+ /// The SftpClient extensions to implement the Task-based Asynchronous Pattern (TAP) over the originally implemented Asynchronous Programming Model (APM).
+ ///
+ public static class SftpClientExtensions
+ {
+ ///
+ /// Asynchronously downloads a remote file specified by the path into the stream.
+ ///
+ ///
+ /// File to download.
+ /// Stream to write the file into.
+ /// The download callback.
+ /// is null.
+ /// is null or contains only whitespace characters.
+ /// Client is not connected.
+ /// Permission to perform the operation was denied by the remote host. -or- A SSH command was denied by the server.
+ /// was not found on the remote host.///
+ /// A SSH error where is the message from the remote host.
+ /// The method was called after the client was disposed.
+ ///
+ /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream.
+ ///
+ public static Task DownloadFileAsync(this SftpClient sftpClient, string path, Stream output, Action downloadCallback = null)
+ {
+ if (sftpClient == null)
+ throw new ArgumentNullException("sftpClient");
+
+ var tcs = new TaskCompletionSource();
+ sftpClient.BeginDownloadFile(path, output, iar =>
+ {
+ try
+ {
+ sftpClient.EndDownloadFile(iar);
+ tcs.TrySetResult(true);
+ }
+ catch (OperationCanceledException)
+ {
+ tcs.TrySetCanceled();
+ }
+ catch (Exception exc)
+ {
+ tcs.TrySetException(exc);
+ }
+ }, null, downloadCallback);
+ return tcs.Task;
+ }
+
+ ///
+ /// Asynchronously retrieves list of files in remote directory.
+ ///
+ ///
+ /// The path.
+ /// The list callback.
+ ///
+ /// A list of files.
+ ///
+ /// The method was called after the client was disposed.
+ public static Task> ListDirectoryAsync(this SftpClient sftpClient, string path, Action listCallback = null)
+ {
+ if (sftpClient == null)
+ throw new ArgumentNullException("sftpClient");
+
+ var tcs = new TaskCompletionSource>();
+ sftpClient.BeginListDirectory(path, iar =>
+ {
+ try
+ {
+ tcs.TrySetResult(sftpClient.EndListDirectory(iar));
+ }
+ catch (OperationCanceledException)
+ {
+ tcs.TrySetCanceled();
+ }
+ catch (Exception exc)
+ {
+ tcs.TrySetException(exc);
+ }
+ }, null, listCallback);
+ return tcs.Task;
+ }
+
+
+ ///
+ /// Asynchronously synchronizes the directories.
+ ///
+ ///
+ /// The source path.
+ /// The destination path.
+ /// The search pattern.
+ ///
+ /// A list of uploaded files.
+ ///
+ /// is null.
+ /// is null or contains only whitespace.
+ /// was not found on the remote host.
+ public static Task> SynchronizeDirectoriesAsync(this SftpClient sftpClient
+ , string sourcePath, string destinationPath, string searchPattern)
+ {
+ if (sftpClient == null)
+ throw new ArgumentNullException("sftpClient");
+
+ return Task>.Factory.FromAsync(sftpClient.BeginSynchronizeDirectories,
+ sftpClient.EndSynchronizeDirectories, sourcePath, destinationPath, searchPattern, null);
+ }
+
+ ///
+ /// Asynchronously uploads stream into remote file. If the file exists it will be overwritten.
+ ///
+ ///
+ /// Data input stream.
+ /// Remote file path.
+ /// The upload callback.
+ /// is null.
+ /// is null or contains only whitespace characters.
+ /// Client is not connected.
+ /// Permission to upload the file was denied by the remote host. -or- A SSH command was denied by the server.
+ /// A SSH error where is the message from the remote host.
+ /// The method was called after the client was disposed.
+ ///
+ /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream.
+ ///
+ public static Task UploadFileAsync(this SftpClient sftpClient, Stream input, string path, Action uploadCallback = null)
+ {
+ return UploadFileAsync(sftpClient, input, path, true, uploadCallback);
+ }
+
+ ///
+ /// Asynchronously uploads stream into remote file.
+ ///
+ ///
+ /// Data input stream.
+ /// Remote file path.
+ /// if set to true then existing file will be overwritten.
+ /// The upload callback.
+ /// is null.
+ /// is null or contains only whitespace characters.
+ /// Client is not connected.
+ /// Permission to upload the file was denied by the remote host. -or- A SSH command was denied by the server.
+ /// A SSH error where is the message from the remote host.
+ /// The method was called after the client was disposed.
+ ///
+ /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream.
+ ///
+ public static Task UploadFileAsync(this SftpClient sftpClient, Stream input, string path, bool canOverride, Action uploadCallback = null)
+ {
+ if (sftpClient == null)
+ throw new ArgumentNullException("sftpClient");
+
+ var tcs = new TaskCompletionSource();
+ sftpClient.BeginUploadFile(input, path, canOverride, iar =>
+ {
+ try
+ {
+ sftpClient.EndUploadFile(iar);
+ tcs.TrySetResult(true);
+ }
+ catch (OperationCanceledException)
+ {
+ tcs.TrySetCanceled();
+ }
+ catch (Exception exc)
+ {
+ tcs.TrySetException(exc);
+ }
+ }, null, uploadCallback);
+ return tcs.Task;
+ }
+
+ }
+}
+#endif
\ No newline at end of file