diff --git a/Microsoft.Bcl.Async/CodePlexKey.snk b/Microsoft.Bcl.Async/CodePlexKey.snk
new file mode 100644
index 000000000..5d44ffe87
Binary files /dev/null and b/Microsoft.Bcl.Async/CodePlexKey.snk differ
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/AsyncPlatformExtensions.WebClient.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/AsyncPlatformExtensions.WebClient.cs
new file mode 100644
index 000000000..cd2e44553
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/AsyncPlatformExtensions.WebClient.cs
@@ -0,0 +1,465 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+///
+/// Provides asynchronous wrappers for .NET Framework operations.
+///
+public static partial class AsyncPlatformExtensions
+{
+ /// Downloads the resource with the specified URI as a string, asynchronously.
+ /// The WebClient.
+ /// The URI from which to download data.
+ /// A Task that contains the downloaded string.
+ public static Task DownloadStringTaskAsync(this WebClient webClient, string address)
+ {
+ return DownloadStringTaskAsync(webClient, webClient.GetUri(address));
+ }
+
+ /// Downloads the resource with the specified URI as a string, asynchronously.
+ /// The WebClient.
+ /// The URI from which to download data.
+ /// A Task that contains the downloaded string.
+ public static Task DownloadStringTaskAsync(this WebClient webClient, Uri address)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ DownloadStringCompletedEventHandler completedHandler = null;
+ completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.DownloadStringCompleted -= completedHandler);
+ webClient.DownloadStringCompleted += completedHandler;
+
+ // Start the async operation.
+ try
+ {
+ webClient.DownloadStringAsync(address, tcs);
+ }
+ catch
+ {
+ webClient.DownloadStringCompleted -= completedHandler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Opens a readable stream for the data downloaded from a resource, asynchronously.
+ /// The WebClient.
+ /// The URI for which the stream should be opened.
+ /// A Task that contains the opened stream.
+ public static Task OpenReadTaskAsync(this WebClient webClient, string address)
+ {
+ return OpenReadTaskAsync(webClient, webClient.GetUri(address));
+ }
+
+ /// Opens a readable stream for the data downloaded from a resource, asynchronously.
+ /// The WebClient.
+ /// The URI for which the stream should be opened.
+ /// A Task that contains the opened stream.
+ public static Task OpenReadTaskAsync(this WebClient webClient, Uri address)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ OpenReadCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.OpenReadCompleted -= handler);
+ webClient.OpenReadCompleted += handler;
+
+ // Start the async operation.
+ try { webClient.OpenReadAsync(address, tcs); }
+ catch
+ {
+ webClient.OpenReadCompleted -= handler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Opens a writeable stream for uploading data to a resource, asynchronously.
+ /// The WebClient.
+ /// The URI for which the stream should be opened.
+ /// A Task that contains the opened stream.
+ public static Task OpenWriteTaskAsync(this WebClient webClient, string address)
+ {
+ return OpenWriteTaskAsync(webClient, webClient.GetUri(address), null);
+ }
+
+ /// Opens a writeable stream for uploading data to a resource, asynchronously.
+ /// The WebClient.
+ /// The URI for which the stream should be opened.
+ /// A Task that contains the opened stream.
+ public static Task OpenWriteTaskAsync(this WebClient webClient, Uri address)
+ {
+ return OpenWriteTaskAsync(webClient, address, null);
+ }
+
+ /// Opens a writeable stream for uploading data to a resource, asynchronously.
+ /// The WebClient.
+ /// The URI for which the stream should be opened.
+ /// The HTTP method that should be used to open the stream.
+ /// A Task that contains the opened stream.
+ public static Task OpenWriteTaskAsync(this WebClient webClient, string address, string method)
+ {
+ return OpenWriteTaskAsync(webClient, webClient.GetUri(address), method);
+ }
+
+ /// Opens a writeable stream for uploading data to a resource, asynchronously.
+ /// The WebClient.
+ /// The URI for which the stream should be opened.
+ /// The HTTP method that should be used to open the stream.
+ /// A Task that contains the opened stream.
+ public static Task OpenWriteTaskAsync(this WebClient webClient, Uri address, string method)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ OpenWriteCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.OpenWriteCompleted -= handler);
+ webClient.OpenWriteCompleted += handler;
+
+ // Start the async operation.
+ try { webClient.OpenWriteAsync(address, method, tcs); }
+ catch
+ {
+ webClient.OpenWriteCompleted -= handler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Uploads data in a string to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadStringTaskAsync(this WebClient webClient, string address, string data)
+ {
+ return UploadStringTaskAsync(webClient, address, null, data);
+ }
+
+ /// Uploads data in a string to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadStringTaskAsync(this WebClient webClient, Uri address, string data)
+ {
+ return UploadStringTaskAsync(webClient, address, null, data);
+ }
+
+ /// Uploads data in a string to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The HTTP method that should be used to upload the data.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadStringTaskAsync(this WebClient webClient, string address, string method, string data)
+ {
+ return UploadStringTaskAsync(webClient, webClient.GetUri(address), method, data);
+ }
+
+ /// Uploads data in a string to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The HTTP method that should be used to upload the data.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadStringTaskAsync(this WebClient webClient, Uri address, string method, string data)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ UploadStringCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.UploadStringCompleted -= handler);
+ webClient.UploadStringCompleted += handler;
+
+ // Start the async operation.
+ try { webClient.UploadStringAsync(address, method, data, tcs); }
+ catch
+ {
+ webClient.UploadStringCompleted -= handler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Converts a path to a Uri using the WebClient's logic.
+ /// Based on WebClient's private GetUri method.
+ private static Uri GetUri(this WebClient webClient, string path)
+ {
+ Uri uri;
+ var baseAddress = webClient.BaseAddress;
+ if (!string.IsNullOrEmpty(baseAddress))
+ {
+ if (!Uri.TryCreate(new Uri(baseAddress), path, out uri))
+ {
+ return new Uri(path);
+
+ }
+ }
+ else if (!Uri.TryCreate(path, UriKind.Absolute, out uri))
+ {
+ return new Uri(path);
+ }
+ return GetUri(webClient, uri);
+ }
+
+#if SILVERLIGHT
+ /// Converts a path to a Uri using the WebClient's logic.
+ /// Based on WebClient's private GetUri method.
+ private static Uri GetUri(this WebClient webClient, Uri address)
+ {
+ if (address == null) throw new ArgumentNullException("address");
+ Uri result = address;
+ if ((!address.IsAbsoluteUri && (!string.IsNullOrEmpty(webClient.BaseAddress))) &&
+ !Uri.TryCreate(new Uri(webClient.BaseAddress), address, out result))
+ {
+ return address;
+ }
+ return result;
+ }
+#else
+ /// Converts a path to a Uri using the WebClient's logic.
+ /// Based on WebClient's private GetUri method.
+ private static Uri GetUri(this WebClient webClient, Uri address)
+ {
+ if (address == null) throw new ArgumentNullException("address");
+
+ Uri result = address;
+ var baseAddress = webClient.BaseAddress;
+ if ((!address.IsAbsoluteUri && (!string.IsNullOrEmpty(baseAddress))) && !Uri.TryCreate(webClient.GetUri(baseAddress), address, out result))
+ {
+ return address;
+ }
+ if ((result.Query != null) && !(result.Query == string.Empty))
+ {
+ return result;
+ }
+
+ var builder = new StringBuilder();
+ string str = string.Empty;
+ var queryString = webClient.QueryString;
+ for (int i = 0; i < queryString.Count; i++)
+ {
+ builder.Append(str + queryString.AllKeys[i] + "=" + queryString[i]);
+ str = "&";
+ }
+ return new UriBuilder(result) { Query = builder.ToString() }.Uri;
+ }
+#endif
+
+#if !SILVERLIGHT
+ /// Downloads the resource with the specified URI as a byte array, asynchronously.
+ /// The WebClient.
+ /// The URI from which to download data.
+ /// A Task that contains the downloaded data.
+ public static Task DownloadDataTaskAsync(this WebClient webClient, string address)
+ {
+ return DownloadDataTaskAsync(webClient, webClient.GetUri(address));
+ }
+
+ /// Downloads the resource with the specified URI as a byte array, asynchronously.
+ /// The WebClient.
+ /// The URI from which to download data.
+ /// A Task that contains the downloaded data.
+ public static Task DownloadDataTaskAsync(this WebClient webClient, Uri address)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ DownloadDataCompletedEventHandler completedHandler = null;
+ completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.DownloadDataCompleted -= completedHandler);
+ webClient.DownloadDataCompleted += completedHandler;
+
+ // Start the async operation.
+ try
+ {
+ webClient.DownloadDataAsync(address, tcs);
+ }
+ catch
+ {
+ webClient.DownloadDataCompleted -= completedHandler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Downloads the resource with the specified URI to a local file, asynchronously.
+ /// The WebClient.
+ /// The URI from which to download data.
+ /// The name of the local file that is to receive the data.
+ /// A Task that contains the downloaded data.
+ public static Task DownloadFileTaskAsync(this WebClient webClient, string address, string fileName)
+ {
+ return DownloadFileTaskAsync(webClient, webClient.GetUri(address), fileName);
+ }
+
+ /// Downloads the resource with the specified URI to a local file, asynchronously.
+ /// The WebClient.
+ /// The URI from which to download data.
+ /// The name of the local file that is to receive the data.
+ /// A Task that contains the downloaded data.
+ public static Task DownloadFileTaskAsync(this WebClient webClient, Uri address, string fileName)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ AsyncCompletedEventHandler completedHandler = null;
+ completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => null, () =>
+ {
+ webClient.DownloadFileCompleted -= completedHandler;
+ });
+ webClient.DownloadFileCompleted += completedHandler;
+
+ // Start the async operation.
+ try
+ {
+ webClient.DownloadFileAsync(address, fileName, tcs);
+ }
+ catch
+ {
+ webClient.DownloadFileCompleted -= completedHandler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Uploads data to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadDataTaskAsync(this WebClient webClient, string address, byte[] data)
+ {
+ return UploadDataTaskAsync(webClient, webClient.GetUri(address), null, data);
+ }
+
+ /// Uploads data to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadDataTaskAsync(this WebClient webClient, Uri address, byte[] data)
+ {
+ return UploadDataTaskAsync(webClient, address, null, data);
+ }
+
+ /// Uploads data to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The HTTP method that should be used to upload the data.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadDataTaskAsync(this WebClient webClient, string address, string method, byte[] data)
+ {
+ return UploadDataTaskAsync(webClient, webClient.GetUri(address), method, data);
+ }
+
+ /// Uploads data to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the data should be uploaded.
+ /// The HTTP method that should be used to upload the data.
+ /// The data to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadDataTaskAsync(this WebClient webClient, Uri address, string method, byte[] data)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ UploadDataCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.UploadDataCompleted -= handler);
+ webClient.UploadDataCompleted += handler;
+
+ // Start the async operation.
+ try { webClient.UploadDataAsync(address, method, data, tcs); }
+ catch
+ {
+ webClient.UploadDataCompleted -= handler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+
+ /// Uploads a file to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the file should be uploaded.
+ /// A path to the file to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadFileTaskAsync(this WebClient webClient, string address, string fileName)
+ {
+ return UploadFileTaskAsync(webClient, webClient.GetUri(address), null, fileName);
+ }
+
+ /// Uploads a file to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the file should be uploaded.
+ /// A path to the file to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadFileTaskAsync(this WebClient webClient, Uri address, string fileName)
+ {
+ return UploadFileTaskAsync(webClient, address, null, fileName);
+ }
+
+ /// Uploads a file to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the file should be uploaded.
+ /// The HTTP method that should be used to upload the file.
+ /// A path to the file to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadFileTaskAsync(this WebClient webClient, string address, string method, string fileName)
+ {
+ return UploadFileTaskAsync(webClient, webClient.GetUri(address), method, fileName);
+ }
+
+ /// Uploads a file to the specified resource, asynchronously.
+ /// The WebClient.
+ /// The URI to which the file should be uploaded.
+ /// The HTTP method that should be used to upload the file.
+ /// A path to the file to upload.
+ /// A Task containing the data in the response from the upload.
+ public static Task UploadFileTaskAsync(this WebClient webClient, Uri address, string method, string fileName)
+ {
+ // Create the task to be returned
+ var tcs = new TaskCompletionSource(address);
+
+ // Setup the callback event handler
+ UploadFileCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => webClient.UploadFileCompleted -= handler);
+ webClient.UploadFileCompleted += handler;
+
+ // Start the async operation.
+ try { webClient.UploadFileAsync(address, method, fileName, tcs); }
+ catch
+ {
+ webClient.UploadFileCompleted -= handler;
+ throw;
+ }
+
+ // Return the task that represents the async operation
+ return tcs.Task;
+ }
+#endif
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/AsyncPlatformExtensions.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/AsyncPlatformExtensions.cs
new file mode 100644
index 000000000..7fa1de24a
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/AsyncPlatformExtensions.cs
@@ -0,0 +1,693 @@
+using System;
+using System.Net;
+using System.Net.Mail;
+using System.Net.NetworkInformation;
+using System.ServiceModel.Discovery;
+using System.Threading.Tasks;
+
+///
+/// Provides asynchronous wrappers for .NET Framework operations.
+///
+public static partial class AsyncPlatformExtensions
+{
+ ///Causes an online announcement (Hello) message to be sent asynchronously with the specified endpoint discovery metadata and user-defined state. The specified is called when the operation completes.
+ ///Task instance.
+ /// The endpoint discovery metadata.
+ /// The source.
+ public static Task AnnounceOnlineTaskAsync(this System.ServiceModel.Discovery.AnnouncementClient source, System.ServiceModel.Discovery.EndpointDiscoveryMetadata discoveryMetadata)
+ {
+ return Task.Factory.FromAsync(source.BeginAnnounceOnline, source.EndAnnounceOnline, discoveryMetadata, null);
+ }
+
+ ///Causes an offline announcement (Bye) message to be sent asynchronously with the specified endpoint discovery metadata and user-defined state. The specified is called when the operation completes.
+ ///Task instance.
+ /// The endpoint discovery metadata.
+ /// The source.
+ public static Task AnnounceOfflineTaskAsync(this System.ServiceModel.Discovery.AnnouncementClient source, System.ServiceModel.Discovery.EndpointDiscoveryMetadata discoveryMetadata)
+ {
+ return Task.Factory.FromAsync(source.BeginAnnounceOffline, source.EndAnnounceOffline, discoveryMetadata, null);
+ }
+
+ ///Begins asynchronously retrieving an incoming request.
+ ///Task object that indicates the status of the asynchronous operation.
+ ///A Win32 function call failed. Check the exception's property to determine the cause of the exception.
+ ///This object has not been started or is currently stopped.
+ ///This object is closed.
+ /// The source.
+ public static Task GetContextAsync(this System.Net.HttpListener source)
+ {
+ return Task.Factory.FromAsync(source.BeginGetContext, source.EndGetContext, null);
+ }
+
+ ///Starts an asynchronous request for the client's X.509 v.3 certificate.
+ ///Task that indicates the status of the operation.
+ /// The source.
+ public static Task GetClientCertificateAsync(this System.Net.HttpListenerRequest source)
+ {
+ return Task.Factory.FromAsync(source.BeginGetClientCertificate, source.EndGetClientCertificate, null);
+ }
+
+ ///Called by clients to begin an asynchronous operation to authenticate the client, and optionally the server, in a client-server connection. This method does not block.
+ ///Task object indicating the status of the asynchronous operation.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///This object has been closed.
+ ///Authentication has already occurred.- or -This stream was used previously to attempt authentication as the server. You cannot use the stream to retry authentication as the client.
+ /// The source.
+ public static Task AuthenticateAsClientAsync(this System.Net.Security.NegotiateStream source)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsClient, source.EndAuthenticateAsClient, null);
+ }
+
+ ///Called by clients to begin an asynchronous operation to authenticate the client, and optionally the server, in a client-server connection. The authentication process uses the specified credentials. This method does not block.
+ ///Task object indicating the status of the asynchronous operation.
+ /// The that is used to establish the identity of the client.
+ /// The Service Principal Name (SPN) that uniquely identifies the server to authenticate.
+ /// is null.- or - is null.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///This object has been closed.
+ ///Authentication has already occurred.- or -This stream was used previously to attempt authentication as the server. You cannot use the stream to retry authentication as the client.
+ /// The source.
+ public static Task AuthenticateAsClientAsync(this System.Net.Security.NegotiateStream source, System.Net.NetworkCredential credential, string targetName)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsClient, source.EndAuthenticateAsClient, credential, targetName, null);
+ }
+
+ ///Called by clients to begin an asynchronous operation to authenticate the client, and optionally the server, in a client-server connection. The authentication process uses the specified credentials and channel binding. This method does not block.
+ ///Task object indicating the status of the asynchronous operation.
+ /// The that is used to establish the identity of the client.
+ /// The that is used for extended protection.
+ /// The Service Principal Name (SPN) that uniquely identifies the server to authenticate.
+ /// is null.- or - is null.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///Authentication has already occurred.- or -This stream was used previously to attempt authentication as the server. You cannot use the stream to retry authentication as the client.
+ ///This object has been closed.
+ /// The source.
+ public static Task AuthenticateAsClientAsync(this System.Net.Security.NegotiateStream source, System.Net.NetworkCredential credential, System.Security.Authentication.ExtendedProtection.ChannelBinding binding, string targetName)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsClient, source.EndAuthenticateAsClient, credential, binding, targetName, null);
+ }
+
+ ///Called by servers to begin an asynchronous operation to authenticate the client, and optionally the server, in a client-server connection. This method does not block.
+ ///Task object indicating the status of the asynchronous operation.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///This object has been closed.
+ ///Windows 95 and Windows 98 are not supported.
+ /// The source.
+ public static Task AuthenticateAsServerAsync(this System.Net.Security.NegotiateStream source)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsServer, source.EndAuthenticateAsServer, null);
+ }
+
+ ///Called by servers to begin an asynchronous operation to authenticate the client, and optionally the server, in a client-server connection. The authentication process uses the specified extended protection policy. This method does not block.
+ ///Task object indicating the status of the asynchronous operation.
+ /// The that is used for extended protection.
+ ///The and on the extended protection policy passed in the parameter are both null.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///Windows 95 and Windows 98 are not supported.
+ ///This object has been closed.
+ /// The source.
+ public static Task AuthenticateAsServerAsync(this System.Net.Security.NegotiateStream source, System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy policy)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsServer, source.EndAuthenticateAsServer, policy, null);
+ }
+
+ ///Called by servers to begin an asynchronous operation to authenticate the client, and optionally the server, in a client-server connection. The authentication process uses the specified server credentials and authentication options. This method does not block.
+ ///Task object indicating the status of the asynchronous operation.
+ /// The that is used to establish the identity of the client.
+ /// One of the values, indicating the security services for the stream.
+ /// One of the values, indicating how the server can use the client's credentials to access resources.
+ /// is null.
+ /// must be , , or ,
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///The authentication failed. You can use this object to retry the authentication.
+ ///This object has been closed.
+ ///Authentication has already occurred.- or -This stream was used previously to attempt authentication as the client. You cannot use the stream to retry authentication as the server.
+ ///Windows 95 and Windows 98 are not supported.
+ /// The source.
+ public static Task AuthenticateAsServerAsync(this System.Net.Security.NegotiateStream source, System.Net.NetworkCredential credential, System.Net.Security.ProtectionLevel requiredProtectionLevel, System.Security.Principal.TokenImpersonationLevel requiredImpersonationLevel)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsServer, source.EndAuthenticateAsServer, credential, requiredProtectionLevel, requiredImpersonationLevel, null);
+ }
+
+ ///Called by clients to begin an asynchronous operation to authenticate the server and optionally the client.
+ ///Task object that indicates the status of the asynchronous operation.
+ /// The name of the server that shares this .
+ /// is null.
+ ///The authentication failed and left this object in an unusable state.
+ ///Authentication has already occurred.-or-Server authentication using this was tried previously.-or- Authentication is already in progress.
+ ///This object has been closed.
+ /// The source.
+ public static Task AuthenticateAsClientAsync(this System.Net.Security.SslStream source, string targetHost)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsClient, source.EndAuthenticateAsClient, targetHost, null);
+ }
+
+ ///Called by servers to begin an asynchronous operation to authenticate the client and optionally the server in a client-server connection.
+ ///Task object indicating the status of the asynchronous operation.
+ /// The X509Certificate used to authenticate the server.
+ /// is null.
+ ///The authentication failed and left this object in an unusable state.
+ ///Authentication has already occurred.-or-Client authentication using this was tried previously.-or- Authentication is already in progress.
+ ///This object has been closed.
+ ///The method is not supported on Windows 95, Windows 98, or Windows Millennium.
+ /// The source.
+ public static Task AuthenticateAsServerAsync(this System.Net.Security.SslStream source, System.Security.Cryptography.X509Certificates.X509Certificate serverCertificate)
+ {
+ return Task.Factory.FromAsync(source.BeginAuthenticateAsServer, source.EndAuthenticateAsServer, serverCertificate, null);
+ }
+
+ ///Starts an asynchronous request for a remote host connection. The host is specified by a host name and a port number.
+ ///Task that represents the asynchronous connection.
+ /// The name of the remote host.
+ /// The port number of the remote host.
+ /// is null.
+ ///The has been closed.
+ ///This method is valid for sockets in the or families.
+ ///The port number is not valid.
+ ///The is ing.
+ ///
+ /// The source.
+ public static Task ConnectAsync(this System.Net.Sockets.TcpClient source, string hostname, int port)
+ {
+ return Task.Factory.FromAsync(source.BeginConnect, source.EndConnect, hostname, port, null);
+ }
+
+ ///Starts an asynchronous request for a remote host connection. The host is specified by an and a port number.
+ ///Task that represents the asynchronous connection.
+ /// The of the remote host.
+ /// The port number of the remote host.
+ /// is null.
+ ///An error occurred when attempting to access the socket. See the Remarks section for more information.
+ ///The has been closed.
+ ///The is not in the socket family.
+ ///The port number is not valid.
+ ///The length of is zero.
+ ///The is ing.
+ ///
+ /// The source.
+ public static Task ConnectAsync(this System.Net.Sockets.TcpClient source, System.Net.IPAddress address, int port)
+ {
+ return Task.Factory.FromAsync(source.BeginConnect, source.EndConnect, address, port, null);
+ }
+
+ ///Starts an asynchronous request for a remote host connection. The host is specified by an array and a port number.
+ ///Task that represents the asynchronous connections.
+ /// At least one , designating the remote host.
+ /// The port number of the remote host.
+ /// is null.
+ ///An error occurred when attempting to access the socket. See the Remarks section for more information.
+ ///The has been closed.
+ ///This method is valid for sockets that use or .
+ ///The port number is not valid.
+ ///The length of is zero.
+ ///The is ing.
+ ///
+ /// The source.
+ public static Task ConnectAsync(this System.Net.Sockets.TcpClient source, System.Net.IPAddress[] ipAddresses, int port)
+ {
+ return Task.Factory.FromAsync(source.BeginConnect, source.EndConnect, ipAddresses, port, null);
+ }
+
+ ///Starts an asynchronous operation to accept an incoming connection attempt.
+ ///Task that represents the asynchronous creation of the .
+ ///An error occurred while attempting to access the socket. See the Remarks section for more information.
+ ///The has been closed.
+ ///
+ /// The source.
+ public static Task AcceptSocketAsync(this System.Net.Sockets.TcpListener source)
+ {
+ return Task.Factory.FromAsync(source.BeginAcceptSocket, source.EndAcceptSocket, null);
+ }
+
+ ///Starts an asynchronous operation to accept an incoming connection attempt.
+ ///Task that represents the asynchronous creation of the .
+ ///An error occurred while attempting to access the socket. See the Remarks section for more information.
+ ///The has been closed.
+ ///
+ /// The source.
+ public static Task AcceptTcpClientAsync(this System.Net.Sockets.TcpListener source)
+ {
+ return Task.Factory.FromAsync(source.BeginAcceptTcpClient, source.EndAcceptTcpClient, null);
+ }
+
+ ///Sends a datagram to a destination asynchronously. The destination is specified by a .
+ ///Task object that represents the asynchronous send.
+ /// A array that contains the data to be sent.
+ /// The number of bytes to send.
+ /// The that represents the destination for the data.
+ /// The source.
+ public static Task SendAsync(this System.Net.Sockets.UdpClient source, byte[] datagram, int bytes, System.Net.IPEndPoint endPoint)
+ {
+ return Task.Factory.FromAsync(source.BeginSend, source.EndSend, datagram, bytes, endPoint, null);
+ }
+
+ ///Sends a datagram to a remote host asynchronously. The destination was specified previously by a call to .
+ ///Task object that represents the asynchronous send.
+ /// A array that contains the data to be sent.
+ /// The number of bytes to send.
+ /// The source.
+ public static Task SendAsync(this System.Net.Sockets.UdpClient source, byte[] datagram, int bytes)
+ {
+ return Task.Factory.FromAsync(source.BeginSend, source.EndSend, datagram, bytes, null);
+ }
+
+ ///Sends a datagram to a remote host asynchronously. The destination was specified previously by a call to .
+ ///Task object that represents the asynchronous send.
+ /// A array that contains the data to be sent.
+ /// The number of bytes to send.
+ /// The host name.
+ /// The host name.
+ /// The source.
+ public static Task SendAsync(this System.Net.Sockets.UdpClient source, byte[] datagram, int bytes, string hostname, int port)
+ {
+ return Task.Factory.FromAsync((callback, state) => source.BeginSend(datagram, bytes, hostname, port, callback, state), source.EndSend, null);
+ }
+
+ ///Starts an asynchronous request to retrieve the stable unicast IP address table on the local computer.
+ ///Task that represents the asynchronous request.
+ ///This method is not implemented on the platform. This method uses the native NotifyStableUnicastIpAddressTable function that is supported on Windows Vista and later.
+ ///The call to the native NotifyStableUnicastIpAddressTable function failed.
+ /// The source.
+ public static Task GetUnicastAddressesAsync(this System.Net.NetworkInformation.IPGlobalProperties source)
+ {
+ return Task.Factory.FromAsync(source.BeginGetUnicastAddresses, source.EndGetUnicastAddresses, null);
+ }
+
+ /// Opens the connection asynchronously.
+ /// The source.
+ /// Task that represents the asynchronous request.
+ public static Task OpenAsync(this System.Data.SqlClient.SqlConnection source)
+ {
+ return OpenAsync(source, System.Threading.CancellationToken.None);
+ }
+
+ /// Opens the connection asynchronously.
+ /// The source.
+ /// The cancellation token.
+ ///Task that represents the asynchronous request.
+ public static Task OpenAsync(this System.Data.SqlClient.SqlConnection source, System.Threading.CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(() => source.Open(), cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , given a callback procedure and state information.
+ ///Task that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns the number of affected rows.
+ ///Any error that occurred while executing the command text.
+ ///The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this .
+ ///2
+ /// The source.
+ public static Task ExecuteNonQueryAsync(this System.Data.SqlClient.SqlCommand source)
+ {
+ return ExecuteNonQueryAsync(source, System.Threading.CancellationToken.None);
+ }
+
+ ///Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this , given a callback procedure and state information.
+ ///Task that can be used to poll or wait for results, or both; this value is also needed when invoking , which returns the number of affected rows.
+ ///Any error that occurred while executing the command text.
+ ///The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this .
+ ///2
+ /// The cancellation token.
+ /// The source.
+ public static Task ExecuteNonQueryAsync(this System.Data.SqlClient.SqlCommand source, System.Threading.CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return TaskServices.FromCancellation(cancellationToken);
+ return Task.Factory.FromAsync(source.BeginExecuteNonQuery, source.EndExecuteNonQuery, null);
+ }
+
+ ///Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and returns results as an object, using a callback procedure.
+ ///Task that can be used to poll, wait for results, or both; this value is also needed when the is called, which returns the results of the command as XML.
+ ///Any error that occurred while executing the command text.
+ ///The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this .
+ ///2
+ /// The source.
+ public static Task ExecuteXmlReaderAsync(this System.Data.SqlClient.SqlCommand source)
+ {
+ return ExecuteXmlReaderAsync(source, System.Threading.CancellationToken.None);
+ }
+
+ ///Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and returns results as an object, using a callback procedure.
+ ///Task that can be used to poll, wait for results, or both; this value is also needed when the is called, which returns the results of the command as XML.
+ ///Any error that occurred while executing the command text.
+ ///The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this .
+ ///2
+ /// The cancellation token.
+ /// The source.
+ public static Task ExecuteXmlReaderAsync(this System.Data.SqlClient.SqlCommand source, System.Threading.CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return TaskServices.FromCancellation(cancellationToken);
+ return Task.Factory.FromAsync(source.BeginExecuteXmlReader, source.EndExecuteXmlReader, null);
+ }
+
+ ///Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and retrieves one or more result sets from the server, given a callback procedure and state information.
+ ///Task that can be used to poll, wait for results, or both; this value is also needed when invoking , which returns a instance which can be used to retrieve the returned rows.
+ ///Any error that occurred while executing the command text.
+ ///The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this .
+ ///2
+ /// The source.
+ public static Task ExecuteReaderAsync(this System.Data.SqlClient.SqlCommand source)
+ {
+ return ExecuteReaderAsync(source, System.Threading.CancellationToken.None);
+ }
+
+ ///Initiates the asynchronous execution of the Transact-SQL statement or stored procedure that is described by this and retrieves one or more result sets from the server, given a callback procedure and state information.
+ ///Task that can be used to poll, wait for results, or both; this value is also needed when invoking , which returns a instance which can be used to retrieve the returned rows.
+ ///Any error that occurred while executing the command text.
+ ///The name/value pair "Asynchronous Processing=true" was not included within the connection string defining the connection for this .
+ ///2
+ /// The cancellation token.
+ /// The source.
+ public static Task ExecuteReaderAsync(this System.Data.SqlClient.SqlCommand source, System.Threading.CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return TaskServices.FromCancellation(cancellationToken);
+ return Task.Factory.FromAsync(source.BeginExecuteReader, source.EndExecuteReader, null);
+ }
+
+ ///Starts an asynchronous method call that returns a .
+ ///The metadata.
+ /// The source.
+ public static Task GetMetadataAsync(this System.ServiceModel.Description.MetadataExchangeClient source)
+ {
+ return Task.Factory.FromAsync(source.BeginGetMetadata, source.EndGetMetadata, null);
+ }
+
+ ///Starts an asynchronous method call that returns a using the specified address, callback, asynchronous state, and download mechanism.
+ ///The metadata obtained from the specified .
+ /// The address of the metadata.
+ /// The value to use when downloading the metadata.
+ /// The source.
+ public static Task GetMetadataAsync(this System.ServiceModel.Description.MetadataExchangeClient source, System.Uri address, System.ServiceModel.Description.MetadataExchangeClientMode mode)
+ {
+ return Task.Factory.FromAsync(source.BeginGetMetadata, source.EndGetMetadata, address, mode, null);
+ }
+
+ ///Starts an asynchronous method call that returns a using the specified address, callback, and asynchronous state.
+ ///The metadata obtained from the specified .
+ /// The address of the metadata.
+ /// The source.
+ public static Task GetMetadataAsync(this System.ServiceModel.Description.MetadataExchangeClient source, System.ServiceModel.EndpointAddress address)
+ {
+ return Task.Factory.FromAsync(source.BeginGetMetadata, source.EndGetMetadata, address, null);
+ }
+
+ ///
+ /// Begins an asynchronous find operation with the specified criteria.
+ ///
+ /// The discovery client.
+ /// The criteria for finding services.
+ /// A Task that represents the asynchronous operation.
+ public static Task FindTaskAsync(
+ this DiscoveryClient discoveryClient, FindCriteria criteria)
+ {
+ // Validate arguments
+ if (discoveryClient == null) throw new ArgumentNullException("discoveryClient");
+
+ // Create a TaskCompletionSource to represent the operation
+ var tcs = new TaskCompletionSource(discoveryClient);
+
+ // Register a handler that will transfer completion results to the TCS Task
+ EventHandler completedHandler = null;
+ completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => discoveryClient.FindCompleted -= completedHandler);
+ discoveryClient.FindCompleted += completedHandler;
+
+ // Start the async operation.
+ try { discoveryClient.FindAsync(criteria, tcs); }
+ catch
+ {
+ discoveryClient.FindCompleted -= completedHandler;
+ throw;
+ }
+
+ // Return the task to represent the asynchronous operation
+ return tcs.Task;
+ }
+
+ ///
+ /// Begins an asynchronous resolve operation with the specified criteria.
+ ///
+ /// The discovery client.
+ /// The criteria for matching a service endpoint.
+ /// A Task that represents the asynchronous operation.
+ public static Task ResolveTaskAsync(
+ this DiscoveryClient discoveryClient, ResolveCriteria criteria)
+ {
+ // Validate arguments
+ if (discoveryClient == null) throw new ArgumentNullException("discoveryClient");
+
+ // Create a TaskCompletionSource to represent the operation
+ var tcs = new TaskCompletionSource(discoveryClient);
+
+ // Register a handler that will transfer completion results to the TCS Task
+ EventHandler completedHandler = null;
+ completedHandler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Result, () => discoveryClient.ResolveCompleted -= completedHandler);
+ discoveryClient.ResolveCompleted += completedHandler;
+
+ // Start the async operation.
+ try { discoveryClient.ResolveAsync(criteria, tcs); }
+ catch
+ {
+ discoveryClient.ResolveCompleted -= completedHandler;
+ throw;
+ }
+
+ // Return the task to represent the asynchronous operation
+ return tcs.Task;
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ /// An IPAddress that identifies the computer that is the destination for the ICMP echo message.
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, IPAddress address)
+ {
+ return SendTaskAsyncCore(ping, address, tcs => ping.SendAsync(address, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ ///
+ /// A String that identifies the computer that is the destination for the ICMP echo message.
+ /// The value specified for this parameter can be a host name or a string representation of an IP address.
+ ///
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, string hostNameOrAddress)
+ {
+ return SendTaskAsyncCore(ping, hostNameOrAddress, tcs => ping.SendAsync(hostNameOrAddress, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ /// An IPAddress that identifies the computer that is the destination for the ICMP echo message.
+ ///
+ /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message)
+ /// to wait for the ICMP echo reply message.
+ ///
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, IPAddress address, int timeout)
+ {
+ return SendTaskAsyncCore(ping, address, tcs => ping.SendAsync(address, timeout, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ ///
+ /// A String that identifies the computer that is the destination for the ICMP echo message.
+ /// The value specified for this parameter can be a host name or a string representation of an IP address.
+ ///
+ ///
+ /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message)
+ /// to wait for the ICMP echo reply message.
+ ///
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, string hostNameOrAddress, int timeout)
+ {
+ return SendTaskAsyncCore(ping, hostNameOrAddress, tcs => ping.SendAsync(hostNameOrAddress, timeout, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ /// An IPAddress that identifies the computer that is the destination for the ICMP echo message.
+ ///
+ /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message)
+ /// to wait for the ICMP echo reply message.
+ ///
+ ///
+ /// A Byte array that contains data to be sent with the ICMP echo message and returned
+ /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
+ ///
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, IPAddress address, int timeout, byte[] buffer)
+ {
+ return SendTaskAsyncCore(ping, address, tcs => ping.SendAsync(address, timeout, buffer, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ ///
+ /// A String that identifies the computer that is the destination for the ICMP echo message.
+ /// The value specified for this parameter can be a host name or a string representation of an IP address.
+ ///
+ ///
+ /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message)
+ /// to wait for the ICMP echo reply message.
+ ///
+ ///
+ /// A Byte array that contains data to be sent with the ICMP echo message and returned
+ /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
+ ///
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, string hostNameOrAddress, int timeout, byte[] buffer)
+ {
+ return SendTaskAsyncCore(ping, hostNameOrAddress, tcs => ping.SendAsync(hostNameOrAddress, timeout, buffer, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ /// An IPAddress that identifies the computer that is the destination for the ICMP echo message.
+ ///
+ /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message)
+ /// to wait for the ICMP echo reply message.
+ ///
+ ///
+ /// A Byte array that contains data to be sent with the ICMP echo message and returned
+ /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
+ ///
+ /// A PingOptions object used to control fragmentation and Time-to-Live values for the ICMP echo message packet.
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, IPAddress address, int timeout, byte[] buffer, PingOptions options)
+ {
+ return SendTaskAsyncCore(ping, address, tcs => ping.SendAsync(address, timeout, buffer, options, tcs));
+ }
+
+ ///
+ /// Asynchronously attempts to send an Internet Control Message Protocol (ICMP) echo message.
+ ///
+ /// The Ping.
+ ///
+ /// A String that identifies the computer that is the destination for the ICMP echo message.
+ /// The value specified for this parameter can be a host name or a string representation of an IP address.
+ ///
+ ///
+ /// An Int32 value that specifies the maximum number of milliseconds (after sending the echo message)
+ /// to wait for the ICMP echo reply message.
+ ///
+ ///
+ /// A Byte array that contains data to be sent with the ICMP echo message and returned
+ /// in the ICMP echo reply message. The array cannot contain more than 65,500 bytes.
+ ///
+ /// A PingOptions object used to control fragmentation and Time-to-Live values for the ICMP echo message packet.
+ /// A task that represents the asynchronous operation.
+ public static Task SendTaskAsync(this Ping ping, string hostNameOrAddress, int timeout, byte[] buffer, PingOptions options)
+ {
+ return SendTaskAsyncCore(ping, hostNameOrAddress, tcs => ping.SendAsync(hostNameOrAddress, timeout, buffer, options, tcs));
+ }
+
+ /// The core implementation of SendTaskAsync.
+ /// The Ping.
+ /// A user-defined object stored in the resulting Task.
+ ///
+ /// A delegate that initiates the asynchronous send.
+ /// The provided TaskCompletionSource must be passed as the user-supplied state to the actual Ping.SendAsync method.
+ ///
+ ///
+ private static Task SendTaskAsyncCore(Ping ping, object userToken, Action> sendAsync)
+ {
+ // Validate arguments
+ if (ping == null) throw new ArgumentNullException("ping");
+
+ // Create a TaskCompletionSource to represent the operation
+ var tcs = new TaskCompletionSource(userToken);
+
+ // Register a handler that will transfer completion results to the TCS Task
+ PingCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => e.Reply, () => ping.PingCompleted -= handler);
+ ping.PingCompleted += handler;
+
+ // Start the async operation.
+ try { sendAsync(tcs); }
+ catch
+ {
+ ping.PingCompleted -= handler;
+ throw;
+ }
+
+ // Return the task to represent the asynchronous operation
+ return tcs.Task;
+ }
+
+ /// Sends an e-mail message asynchronously.
+ /// The client.
+ /// A String that contains the address information of the message sender.
+ /// A String that contains the address that the message is sent to.
+ /// A String that contains the subject line for the message.
+ /// A String that contains the message body.
+ /// A Task that represents the asynchronous send.
+ public static Task SendTaskAsync(this SmtpClient smtpClient, string from, string recipients, string subject, string body)
+ {
+ var message = new MailMessage(from, recipients, subject, body);
+ return SendTaskAsync(smtpClient, message);
+ }
+
+ /// Sends an e-mail message asynchronously.
+ /// The client.
+ /// A MailMessage that contains the message to send.
+ /// A Task that represents the asynchronous send.
+ public static Task SendTaskAsync(this SmtpClient smtpClient, MailMessage message)
+ {
+ return SendTaskAsyncCore(smtpClient, message, tcs => smtpClient.SendAsync(message, tcs));
+ }
+
+ /// The core implementation of SendTaskAsync.
+ /// The client.
+ /// The user-supplied state.
+ ///
+ /// A delegate that initiates the asynchronous send.
+ /// The provided TaskCompletionSource must be passed as the user-supplied state to the actual SmtpClient.SendAsync method.
+ ///
+ ///
+ private static Task SendTaskAsyncCore(SmtpClient smtpClient, object userToken, Action> sendAsync)
+ {
+ // Validate arguments
+ if (smtpClient == null) throw new ArgumentNullException("smtpClient");
+
+ // Create a TaskCompletionSource to represent the operation
+ var tcs = new TaskCompletionSource(userToken);
+
+ // Register a handler that will transfer completion results to the TCS Task
+ SendCompletedEventHandler handler = null;
+ handler = (sender, e) => TaskServices.HandleEapCompletion(tcs, true, e, () => null, () => smtpClient.SendCompleted -= handler);
+ smtpClient.SendCompleted += handler;
+
+ // Start the async operation.
+ try { sendAsync(tcs); }
+ catch
+ {
+ smtpClient.SendCompleted -= handler;
+ throw;
+ }
+
+ // Return the task to represent the asynchronous operation
+ return tcs.Task;
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Microsoft.Threading.Tasks.Extensions.Desktop.csproj b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Microsoft.Threading.Tasks.Extensions.Desktop.csproj
new file mode 100644
index 000000000..80c6abae5
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Microsoft.Threading.Tasks.Extensions.Desktop.csproj
@@ -0,0 +1,92 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9D4342DE-EF5A-4ACF-8AFC-0C777D23577B}
+ Library
+ Properties
+ System
+ Microsoft.Threading.Tasks.Extensions.Desktop
+ v4.0
+ 512
+ SAK
+ SAK
+ SAK
+ SAK
+ ..\..\
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ bin\Debug\Microsoft.Threading.Tasks.Extensions.Desktop.xml
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ bin\Release\Microsoft.Threading.Tasks.Extensions.Desktop.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\net40\System.Runtime.dll
+
+
+
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\net40\System.Threading.Tasks.dll
+
+
+
+
+
+
+
+
+
+
+ Threading\Tasks\TaskServices.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Microsoft.Threading.Tasks.Extensions.Desktop.csproj.vspscc b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Microsoft.Threading.Tasks.Extensions.Desktop.csproj.vspscc
new file mode 100644
index 000000000..b6d32892f
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Microsoft.Threading.Tasks.Extensions.Desktop.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Net/DnsEx.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Net/DnsEx.cs
new file mode 100644
index 000000000..f963007bd
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Net/DnsEx.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Threading.Tasks;
+
+namespace System.Net
+{
+ /// Provides asynchronous wrappers for the class.
+ public static class DnsEx
+ {
+ /// Asynchronously returns the Internet Protocol (IP) addresses for the specified host.
+ /// The host name or IP address to resolve.
+ /// An array of type System.Net.IPAddress that holds the IP addresses for the host specified.
+ public static Task GetHostAddressesAsync(string hostNameOrAddress)
+ {
+ return Task.Factory.FromAsync(Dns.BeginGetHostAddresses, Dns.EndGetHostAddresses, hostNameOrAddress, null);
+ }
+
+ /// Asynchronously resolves an IP address to an System.Net.IPHostEntry instance.
+ /// The IP address to resolve.
+ /// An System.Net.IPHostEntry instance that contains address information about the host.
+ public static Task GetHostEntryAsync(IPAddress address)
+ {
+ return Task.Factory.FromAsync(Dns.BeginGetHostEntry, Dns.EndGetHostEntry, address, null);
+ }
+
+ /// Asynchronously resolves an IP address to an System.Net.IPHostEntry instance.
+ /// The host name or IP address to resolve.
+ /// An System.Net.IPHostEntry instance that contains address information about the host.
+ public static Task GetHostEntryAsync(string hostNameOrAddress)
+ {
+ return Task.Factory.FromAsync(Dns.BeginGetHostEntry, Dns.EndGetHostEntry, hostNameOrAddress, null);
+ }
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Properties/AssemblyInfo.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..beda9c649
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Threading.Tasks.Extensions.Desktop")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("Microsoft.Threading.Tasks.Extensions.Desktop")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/app.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/app.config
new file mode 100644
index 000000000..a6a2b7fa9
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/app.config
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/packages.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/packages.config
new file mode 100644
index 000000000..92ec9f85a
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Desktop/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Microsoft.Threading.Tasks.Extensions.Phone.csproj b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Microsoft.Threading.Tasks.Extensions.Phone.csproj
new file mode 100644
index 000000000..72879d885
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Microsoft.Threading.Tasks.Extensions.Phone.csproj
@@ -0,0 +1,101 @@
+
+
+
+ Debug
+ AnyCPU
+ 10.0.20506
+ 2.0
+ {AECCDA63-2C7E-4F94-B609-BA552C619EB3}
+ {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ Library
+ Properties
+ Microsoft.Threading.Tasks.Phone
+ Microsoft.Threading.Tasks.Extensions.Phone
+ v4.0
+ $(TargetFrameworkVersion)
+ WindowsPhone71
+ Silverlight
+ false
+ false
+ true
+ SAK
+ SAK
+ SAK
+ SAK
+ ..\..\
+ true
+ true
+
+
+ true
+ full
+ false
+ Bin\Debug
+ TRACE;DEBUG;SILVERLIGHT;WINDOWS_PHONE
+ true
+ true
+ prompt
+ 4
+ Bin\Debug\Microsoft.Threading.Tasks.Extensions.Phone.xml
+
+
+ pdbonly
+ true
+ Bin\Release
+ TRACE;SILVERLIGHT;WINDOWS_PHONE
+ true
+ true
+ prompt
+ 4
+ Bin\Release\Microsoft.Threading.Tasks.Extensions.Phone.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\sl4-windowsphone71\System.Runtime.dll
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\sl4-windowsphone71\System.Threading.Tasks.dll
+
+
+
+
+
+
+ AsyncPlatformExtensions.WebClient.cs
+
+
+ AsyncPlatformExtensions.Dispatcher.cs
+
+
+ Threading\Tasks\TaskServices.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Microsoft.Threading.Tasks.Extensions.Phone.csproj.vspscc b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Microsoft.Threading.Tasks.Extensions.Phone.csproj.vspscc
new file mode 100644
index 000000000..b6d32892f
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Microsoft.Threading.Tasks.Extensions.Phone.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Properties/AssemblyInfo.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..2ead716a2
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/Properties/AssemblyInfo.cs
@@ -0,0 +1,19 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Threading.Tasks.Extensions.Phone")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("Microsoft.Threading.Tasks.Extensions.Phone")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/app.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/app.config
new file mode 100644
index 000000000..a6a2b7fa9
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/app.config
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/packages.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/packages.config
new file mode 100644
index 000000000..52dc8d017
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Phone/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/AsyncPlatformExtensions.Dispatcher.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/AsyncPlatformExtensions.Dispatcher.cs
new file mode 100644
index 000000000..c7006ca23
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/AsyncPlatformExtensions.Dispatcher.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using System.Windows;
+
+///
+/// Provides asynchronous wrappers for .NET Framework operations.
+///
+public static partial class AsyncPlatformExtensions
+{
+ /// Asynchronously invokes an Action on the Dispatcher.
+ /// The Dispatcher.
+ /// The action to invoke.
+ /// A Task that represents the execution of the action.
+ public static Task InvokeAsync(this System.Windows.Threading.Dispatcher dispatcher, Action action)
+ {
+ if (dispatcher == null) throw new ArgumentNullException("dispatcher");
+ if (action == null) throw new ArgumentNullException("action");
+
+ var tcs = new TaskCompletionSource();
+ dispatcher.BeginInvoke(new Action(() =>
+ {
+ try
+ {
+ action();
+ tcs.TrySetResult(default(VoidTaskResult));
+ }
+ catch (Exception exc)
+ {
+ tcs.TrySetException(exc);
+ }
+ }));
+ return tcs.Task;
+ }
+
+ /// Asynchronously invokes an Action on the Dispatcher.
+ /// The Dispatcher.
+ /// The function to invoke.
+ /// A Task that represents the execution of the function.
+ public static Task InvokeAsync(this System.Windows.Threading.Dispatcher dispatcher, Func function)
+ {
+ if (dispatcher == null) throw new ArgumentNullException("dispatcher");
+ if (function == null) throw new ArgumentNullException("function");
+
+ var tcs = new TaskCompletionSource();
+ dispatcher.BeginInvoke(new Action(() =>
+ {
+ try
+ {
+ var result = function();
+ tcs.TrySetResult(result);
+ }
+ catch (Exception exc)
+ {
+ tcs.TrySetException(exc);
+ }
+ }));
+ return tcs.Task;
+ }
+}
+
+/// Used with Task(of void)
+internal struct VoidTaskResult { }
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Microsoft.Threading.Tasks.Extensions.Silverlight.csproj b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Microsoft.Threading.Tasks.Extensions.Silverlight.csproj
new file mode 100644
index 000000000..fd6ad617b
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Microsoft.Threading.Tasks.Extensions.Silverlight.csproj
@@ -0,0 +1,108 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.50727
+ 2.0
+ {E4616E51-1FE7-4007-B85E-B6108FD2F0D1}
+ {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ Library
+ Properties
+ Microsoft
+ Microsoft.Threading.Tasks.Extensions.Silverlight
+ Silverlight
+ v4.0
+ $(TargetFrameworkVersion)
+ false
+ true
+ true
+ SAK
+ SAK
+ SAK
+ SAK
+
+ ..\..\
+ true
+
+
+
+ v3.5
+
+
+ true
+ full
+ false
+ Bin\Debug
+ DEBUG;TRACE;SILVERLIGHT
+ true
+ true
+ prompt
+ 4
+ Bin\Debug\Microsoft.Threading.Tasks.Extensions.Silverlight.xml
+
+
+ pdbonly
+ true
+ Bin\Release
+ TRACE;SILVERLIGHT
+ true
+ true
+ prompt
+ 4
+ Bin\Release\Microsoft.Threading.Tasks.Extensions.Silverlight.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\sl4\System.Runtime.dll
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\sl4\System.Threading.Tasks.dll
+
+
+
+
+ $(TargetFrameworkDirectory)System.Core.dll
+
+
+
+
+
+
+
+ AsyncPlatformExtensions.WebClient.cs
+
+
+ Threading\Tasks\TaskServices.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Microsoft.Threading.Tasks.Extensions.Silverlight.csproj.vspscc b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Microsoft.Threading.Tasks.Extensions.Silverlight.csproj.vspscc
new file mode 100644
index 000000000..b6d32892f
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Microsoft.Threading.Tasks.Extensions.Silverlight.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Properties/AssemblyInfo.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..283df850c
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Threading.Tasks.Extensions.Silverlight")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("Microsoft.Threading.Tasks.Extensions.Silverlight")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/app.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/app.config
new file mode 100644
index 000000000..a6a2b7fa9
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/app.config
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/packages.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/packages.config
new file mode 100644
index 000000000..83ce40645
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions.Silverlight/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/AsyncExtensions.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/AsyncExtensions.cs
new file mode 100644
index 000000000..6d840c9fe
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/AsyncExtensions.cs
@@ -0,0 +1,363 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+///
+/// Provides asynchronous wrappers for .NET Framework operations.
+///
+public static partial class AsyncExtensions
+{
+ ///
+ ///Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
+ ///
+ ///A Task that represents the asynchronous read.
+ /// The source.
+ /// The buffer to read data into.
+ /// The byte offset in at which to begin reading.
+ /// The maximum number of bytes to read.
+ ///The array length minus is less than .
+ /// is null.
+ /// or is negative.
+ ///An asynchronous read was attempted past the end of the file.
+ public static Task ReadAsync(this System.IO.Stream source, byte[] buffer, int offset, int count)
+ {
+ return ReadAsync(source, buffer, offset, count, System.Threading.CancellationToken.None);
+ }
+
+ ///
+ ///Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
+ ///
+ ///A Task that represents the asynchronous read.
+ /// The source.
+ /// The buffer to read data into.
+ /// The byte offset in at which to begin reading.
+ /// The maximum number of bytes to read.
+ /// The cancellation token.
+ ///The array length minus is less than .
+ /// is null.
+ /// or is negative.
+ ///An asynchronous read was attempted past the end of the file.
+ public static Task ReadAsync(this System.IO.Stream source, byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return TaskServices.FromCancellation(cancellationToken);
+ return Task.Factory.FromAsync(source.BeginRead, source.EndRead, buffer, offset, count, null);
+ }
+
+ ///
+ ///Writes asynchronously a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
+ ///
+ ///A Task that represents the asynchronous write.
+ /// The source.
+ /// The buffer containing data to write to the current stream.
+ /// The zero-based byte offset in at which to begin copying bytes to the current stream.
+ /// The maximum number of bytes to write.
+ /// length minus is less than .
+ /// is null.
+ /// or is negative.
+ ///The stream does not support writing.
+ ///The stream is closed.
+ ///An I/O error occurred.
+ public static Task WriteAsync(this System.IO.Stream source, byte[] buffer, int offset, int count)
+ {
+ return WriteAsync(source, buffer, offset, count, System.Threading.CancellationToken.None);
+ }
+
+ ///
+ ///Writes asynchronously a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
+ ///
+ ///A Task that represents the asynchronous write.
+ /// The source.
+ /// The buffer containing data to write to the current stream.
+ /// The zero-based byte offset in at which to begin copying bytes to the current stream.
+ /// The maximum number of bytes to write.
+ /// The cancellation token.
+ /// length minus is less than .
+ /// is null.
+ /// or is negative.
+ ///The stream does not support writing.
+ ///The stream is closed.
+ ///An I/O error occurred.
+ public static Task WriteAsync(this System.IO.Stream source, byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return TaskServices.FromCancellation(cancellationToken);
+ return Task.Factory.FromAsync(source.BeginWrite, source.EndWrite, buffer, offset, count, null);
+ }
+
+ ///
+ ///Flushes asynchronously the current stream.
+ ///
+ ///A Task that represents the asynchronous flush.
+ public static Task FlushAsync(this System.IO.Stream source)
+ {
+ return FlushAsync(source, System.Threading.CancellationToken.None);
+ }
+
+ ///
+ ///Flushes asynchronously the current stream.
+ ///
+ ///A Task that represents the asynchronous flush.
+ public static Task FlushAsync(this System.IO.Stream source, System.Threading.CancellationToken cancellationToken)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ return TaskServices.FromCancellation(cancellationToken);
+ return Task.Factory.StartNew(s => ((System.IO.Stream)s).Flush(), source, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///
+ /// Reads all the bytes from the current stream and writes them to the destination stream.
+ ///
+ /// The source stream.
+ /// The stream that will contain the contents of the current stream.
+ /// A Task that represents the asynchronous operation.
+ public static Task CopyToAsync(this Stream source, Stream destination)
+ {
+ return CopyToAsync(source, destination, 0x1000);
+ }
+
+ ///
+ /// Reads all the bytes from the current stream and writes them to the destination stream.
+ ///
+ /// The source stream.
+ /// The stream that will contain the contents of the current stream.
+ /// The size of the buffer. This value must be greater than zero. The default size is 4096.
+ /// A Task that represents the asynchronous operation.
+ public static Task CopyToAsync(this Stream source, Stream destination, int bufferSize)
+ {
+ return CopyToAsync(source, destination, bufferSize, CancellationToken.None);
+ }
+
+ ///
+ /// Reads all the bytes from the current stream and writes them to the destination stream.
+ ///
+ /// The source stream.
+ /// The stream that will contain the contents of the current stream.
+ /// The size of the buffer. This value must be greater than zero. The default size is 4096.
+ /// The cancellation token to use to cancel the asynchronous operation.
+ /// A Task that represents the asynchronous operation.
+ public static Task CopyToAsync(this Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (destination == null) throw new ArgumentNullException("destination");
+ if (bufferSize <= 0) throw new ArgumentOutOfRangeException("bufferSize");
+ if (!source.CanRead && !source.CanWrite) throw new ObjectDisposedException("source");
+ if (!destination.CanRead && !destination.CanWrite) throw new ObjectDisposedException("destination");
+ if (!source.CanRead) throw new NotSupportedException();
+ if (!destination.CanWrite) throw new NotSupportedException();
+
+ return CopyToAsyncInternal(source, destination, bufferSize, cancellationToken);
+ }
+
+ ///
+ /// Reads all the bytes from the current stream and writes them to the destination stream.
+ ///
+ /// The source stream.
+ /// The stream that will contain the contents of the current stream.
+ /// The size of the buffer. This value must be greater than zero. The default size is 4096.
+ /// The cancellation token to use to cancel the asynchronous operation.
+ /// A Task that represents the asynchronous operation.
+ private static async Task CopyToAsyncInternal(this Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ byte[] buffer = new byte[bufferSize];
+ int bytesRead;
+ while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) > 0)
+ {
+ await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Reads a maximum of count characters from the reader asynchronously and writes
+ /// the data to buffer, beginning at index.
+ ///
+ ///
+ /// When the operation completes, contains the specified character array with the
+ /// values between index and (index + count - 1) replaced by the characters read
+ /// from the current source.
+ ///
+ ///
+ /// The maximum number of characters to read. If the end of the stream is reached
+ /// before count of characters is read into buffer, the current method returns.
+ ///
+ /// The place in buffer at which to begin writing.
+ /// the source reader.
+ /// A Task that represents the asynchronous operation.
+ public static Task ReadAsync(this TextReader source, char[] buffer, int index, int count)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return Task.Factory.StartNew(() => source.Read(buffer, index, count), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///
+ /// Reads asynchronously a maximum of count characters from the current stream, and writes the
+ /// data to buffer, beginning at index.
+ ///
+ /// The source reader.
+ ///
+ /// When this method returns, this parameter contains the specified character
+ /// array with the values between index and (index + count -1) replaced by the
+ /// characters read from the current source.
+ ///
+ /// The position in buffer at which to begin writing.
+ /// The maximum number of characters to read.
+ /// A Task that represents the asynchronous operation.
+ public static Task ReadBlockAsync(this TextReader source, char[] buffer, int index, int count)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return Task.Factory.StartNew(() => source.ReadBlock(buffer, index, count), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///
+ /// Reads a line of characters from the reader and returns the string asynchronously.
+ ///
+ /// the source reader.
+ /// A Task that represents the asynchronous operation.
+ public static Task ReadLineAsync(this TextReader source)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return Task.Factory.StartNew(() => source.ReadLine(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///
+ /// Reads all characters from the current position to the end of the TextReader
+ /// and returns them as one string asynchronously.
+ ///
+ /// the source reader.
+ /// A Task that represents the asynchronous operation.
+ public static Task ReadToEndAsync(this TextReader source)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ return Task.Factory.StartNew(() => source.ReadToEnd(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a string asynchronously to a text stream.
+ /// The writer.
+ /// The string to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteAsync(this TextWriter target, string value)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.Write(value), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a char asynchronously to a text stream.
+ /// The writer.
+ /// The char to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteAsync(this TextWriter target, char value)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.Write(value), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a char array asynchronously to a text stream.
+ /// The writer.
+ /// The buffer to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteAsync(this TextWriter target, char[] buffer)
+ {
+ return WriteAsync(target, buffer, 0, buffer.Length);
+ }
+
+ /// Writes a subarray of characters asynchronously to a text stream.
+ /// The writer.
+ /// The buffer to write.
+ /// Starting index in the buffer.
+ /// The number of characters to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteAsync(this TextWriter target, char[] buffer, int index, int count)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.Write(buffer, index, count), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a line terminator asynchronously to a text stream.
+ /// The writer.
+ /// A Task representing the asynchronous write.
+ public static Task WriteLineAsync(this TextWriter target)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.WriteLine(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a string followed by a line terminator asynchronously to a text stream.
+ /// The writer.
+ /// The string to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteLineAsync(this TextWriter target, string value)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.WriteLine(value), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a char followed by a line terminator asynchronously to a text stream.
+ /// The writer.
+ /// The char to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteLineAsync(this TextWriter target, char value)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.WriteLine(value), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Writes a char array followed by a line terminator asynchronously to a text stream.
+ /// The writer.
+ /// The buffer to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteLineAsync(this TextWriter target, char[] buffer)
+ {
+ return WriteLineAsync(target, buffer, 0, buffer.Length);
+ }
+
+ /// Writes a subarray of characters followed by a line terminator asynchronously to a text stream.
+ /// The writer.
+ /// The buffer to write.
+ /// Starting index in the buffer.
+ /// The number of characters to write.
+ /// A Task representing the asynchronous write.
+ public static Task WriteLineAsync(this TextWriter target, char[] buffer, int index, int count)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.WriteLine(buffer, index, count), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///
+ /// Clears all buffers for the current writer and causes any buffered data to
+ /// be written to the underlying device.
+ ///
+ /// The writer.
+ /// A Task representing the asynchronous flush.
+ public static Task FlushAsync(this TextWriter target)
+ {
+ if (target == null) throw new ArgumentNullException("target");
+ return Task.Factory.StartNew(() => target.Flush(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ ///Starts an asynchronous request for a web resource.
+ ///Task that represents the asynchronous request.
+ ///The stream is already in use by a previous call to .
+ ///
+ /// The source.
+ public static Task GetResponseAsync(this System.Net.WebRequest source)
+ {
+ return Task.Factory.StartNew(() =>
+ Task.Factory.FromAsync(source.BeginGetResponse, source.EndGetResponse, null),
+ CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap();
+ }
+
+ ///Starts an asynchronous request for a object to use to write data.
+ ///Task that represents the asynchronous request.
+ ///The property is GET and the application writes to the stream.
+ ///The stream is being used by a previous call to .
+ ///No write stream is available.
+ ///
+ /// The source.
+ public static Task GetRequestStreamAsync(this System.Net.WebRequest source)
+ {
+ return Task.Factory.StartNew(() =>
+ Task.Factory.FromAsync(source.BeginGetRequestStream, source.EndGetRequestStream, null),
+ CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap();
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Microsoft.Threading.Tasks.Extensions.csproj b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Microsoft.Threading.Tasks.Extensions.csproj
new file mode 100644
index 000000000..2bbdb4bca
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Microsoft.Threading.Tasks.Extensions.csproj
@@ -0,0 +1,89 @@
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {D9B6763A-CDAA-47F0-A227-3CA12C3C7FA6}
+ Library
+ Properties
+ System
+ Microsoft.Threading.Tasks.Extensions
+ v4.0
+ Profile88
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SAK
+ SAK
+ SAK
+ SAK
+ ..\..\
+ true
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NO_TIMER_ROOT
+ prompt
+ 4
+ bin\Debug\Microsoft.Threading.Tasks.Extensions.xml
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NO_TIMER_ROOT
+ prompt
+ 4
+ bin\Release\Microsoft.Threading.Tasks.Extensions.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+ Threading\Tasks\TaskServices.cs
+
+
+
+
+
+
+ {b27b5e06-fd10-427a-96e3-770c6a1268d6}
+ Microsoft.Threading.Tasks
+
+
+
+
+
+
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Microsoft.Threading.Tasks.Extensions.csproj.vspscc b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Microsoft.Threading.Tasks.Extensions.csproj.vspscc
new file mode 100644
index 000000000..b6d32892f
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Microsoft.Threading.Tasks.Extensions.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Properties/AssemblyInfo.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..56e0e5757
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Threading.Tasks.Extensions")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("Microsoft.Threading.Tasks.Extensions")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/app.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/app.config
new file mode 100644
index 000000000..a6a2b7fa9
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/app.config
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/packages.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/packages.config
new file mode 100644
index 000000000..2384716da
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks.Extensions/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/AwaitExtensions.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/AwaitExtensions.cs
new file mode 100644
index 000000000..5876f47d0
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/AwaitExtensions.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Diagnostics.Contracts;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Runtime.CompilerServices;
+using Microsoft.Runtime.CompilerServices;
+
+///
+/// Provides extension methods for threading-related types.
+///
+public static class AwaitExtensions
+{
+ /// Cancels the after the specified duration.
+ /// The CancellationTokenSource.
+ /// The due time in milliseconds for the source to be canceled.
+ public static void CancelAfter(this CancellationTokenSource source, int dueTime)
+ {
+ if (source == null) throw new NullReferenceException();
+ if (dueTime < -1) throw new ArgumentOutOfRangeException("dueTime");
+ Contract.EndContractBlock();
+
+ Timer timer = null;
+ timer = new Timer(state =>
+ {
+ ((IDisposable)timer).Dispose();
+ TimerManager.Remove(timer);
+ try { source.Cancel(); }
+ catch (ObjectDisposedException) { }
+ }, null, Timeout.Infinite, Timeout.Infinite);
+
+ TimerManager.Add(timer);
+ timer.Change(dueTime, Timeout.Infinite);
+ }
+
+ /// Cancels the after the specified duration.
+ /// The CancellationTokenSource.
+ /// The due time for the source to be canceled.
+ public static void CancelAfter(this CancellationTokenSource source, TimeSpan dueTime)
+ {
+ long milliseconds = (long)dueTime.TotalMilliseconds;
+ if (milliseconds < -1 || milliseconds > Int32.MaxValue) throw new ArgumentOutOfRangeException("dueTime");
+ CancelAfter(source, (int)milliseconds);
+ }
+
+ /// Gets an awaiter used to await this .
+ /// The task to await.
+ /// An awaiter instance.
+ public static TaskAwaiter GetAwaiter(this Task task)
+ {
+ if (task == null) throw new ArgumentNullException("task");
+ return new TaskAwaiter(task);
+ }
+
+ /// Gets an awaiter used to await this .
+ /// Specifies the type of data returned by the task.
+ /// The task to await.
+ /// An awaiter instance.
+ public static TaskAwaiter GetAwaiter(this Task task)
+ {
+ if (task == null) throw new ArgumentNullException("task");
+ return new TaskAwaiter(task);
+ }
+
+ /// Creates and configures an awaitable object for awaiting the specified task.
+ /// The task to be awaited.
+ ///
+ /// true to automatic marshag back to the original call site's current SynchronizationContext
+ /// or TaskScheduler; otherwise, false.
+ ///
+ /// The instance to be awaited.
+ public static ConfiguredTaskAwaitable ConfigureAwait(this Task task, bool continueOnCapturedContext)
+ {
+ if (task == null) throw new ArgumentNullException("task");
+ return new ConfiguredTaskAwaitable(task, continueOnCapturedContext);
+ }
+
+ /// Creates and configures an awaitable object for awaiting the specified task.
+ /// The task to be awaited.
+ ///
+ /// true to automatic marshag back to the original call site's current SynchronizationContext
+ /// or TaskScheduler; otherwise, false.
+ ///
+ /// The instance to be awaited.
+ public static ConfiguredTaskAwaitable ConfigureAwait(this Task task, bool continueOnCapturedContext)
+ {
+ if (task == null) throw new ArgumentNullException("task");
+ return new ConfiguredTaskAwaitable(task, continueOnCapturedContext);
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Diagnostics/Contracts/Contract.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Diagnostics/Contracts/Contract.cs
new file mode 100644
index 000000000..523d0f36d
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Diagnostics/Contracts/Contract.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+namespace System.Diagnostics.Contracts
+{
+ internal class Contract
+ {
+ public static void Assert(bool condition, string message = null)
+ {
+ Debug.Assert(condition, message);
+ }
+
+ public static void EndContractBlock()
+ {
+ }
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Microsoft.Threading.Tasks.csproj b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Microsoft.Threading.Tasks.csproj
new file mode 100644
index 000000000..ba664dfb0
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Microsoft.Threading.Tasks.csproj
@@ -0,0 +1,91 @@
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {B27B5E06-FD10-427A-96E3-770C6A1268D6}
+ Library
+ Properties
+ System
+ Microsoft.Threading.Tasks
+ v4.0
+ Profile88
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SAK
+ SAK
+ SAK
+ SAK
+ ..\..\
+ true
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NO_TIMER_ROOT
+ prompt
+ 4
+ bin\Debug\Microsoft.Threading.Tasks.xml
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NO_TIMER_ROOT
+ prompt
+ 4
+ bin\Release\Microsoft.Threading.Tasks.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll
+
+
+ ..\..\packages\Microsoft.Bcl.1.0.19\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Microsoft.Threading.Tasks.csproj.vspscc b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Microsoft.Threading.Tasks.csproj.vspscc
new file mode 100644
index 000000000..b6d32892f
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Microsoft.Threading.Tasks.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Progress.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Progress.cs
new file mode 100644
index 000000000..b00620568
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Progress.cs
@@ -0,0 +1,108 @@
+// NOTE: Although this looks very similar to the Progress class available in the framework, the reason this is here is due to the lack of ability to make this
+// compatible due to EventHandler difference. Note that in 4.0, EventHandler has a constraint on EventArgs, in 4.5 we removed it.
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace Microsoft
+{
+ /// Event handler for progress reports.
+ /// Specifies the type of data for the progress report.
+ /// The sender of the report.
+ /// The reported value.
+ public delegate void ProgressEventHandler(object sender, T value);
+
+ ///
+ /// Provides an IProgress{T} that invokes callbacks for each reported progress value.
+ ///
+ /// Specifies the type of the progress report value.
+ ///
+ /// Any handler provided to the constructor or event handlers registered with
+ /// the event are invoked through a
+ /// instance captured
+ /// when the instance is constructed. If there is no current SynchronizationContext
+ /// at the time of construction, the callbacks will be invoked on the ThreadPool.
+ ///
+ public class Progress : IProgress
+ {
+ /// The synchronization context captured upon construction. This will never be null.
+ private readonly SynchronizationContext m_synchronizationContext;
+ /// The handler specified to the constructor. This may be null.
+ private readonly Action m_handler;
+ /// A cached delegate used to post invocation to the synchronization context.
+ private readonly SendOrPostCallback m_invokeHandlers;
+
+ /// Initializes the .
+ public Progress()
+ {
+ m_synchronizationContext = SynchronizationContext.Current ?? ProgressStatics.DefaultContext;
+ Contract.Assert(m_synchronizationContext != null);
+ m_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
+ }
+
+ /// Initializes the with the specified callback.
+ ///
+ /// A handler to invoke for each reported progress value. This handler will be invoked
+ /// in addition to any delegates registered with the event.
+ ///
+ /// The is null (Nothing in Visual Basic).
+ public Progress(Action handler)
+ : this()
+ {
+ if (handler == null) throw new ArgumentNullException("handler");
+ m_handler = handler;
+ }
+
+ /// Raised for each reported progress value.
+ ///
+ /// Handlers registered with this event will be invoked on the
+ /// captured when the instance was constructed.
+ ///
+ public event ProgressEventHandler ProgressChanged;
+
+ /// Reports a progress change.
+ /// The value of the updated progress.
+ protected virtual void OnReport(T value)
+ {
+ // If there's no handler, don't bother going through the sync context.
+ // Inside the callback, we'll need to check again, in case
+ // an event handler is removed between now and then.
+ Action handler = m_handler;
+ ProgressEventHandler changedEvent = ProgressChanged;
+ if (handler != null || changedEvent != null)
+ {
+ // Post the processing to the sync context.
+ // (If T is a value type, it will get boxed here.)
+ m_synchronizationContext.Post(m_invokeHandlers, value);
+ }
+ }
+
+ /// Reports a progress change.
+ /// The value of the updated progress.
+ void IProgress.Report(T value) { OnReport(value); }
+
+ /// Invokes the action and event callbacks.
+ /// The progress value.
+ private void InvokeHandlers(object state)
+ {
+ T value = (T)state;
+
+ Action handler = m_handler;
+ ProgressEventHandler changedEvent = ProgressChanged;
+
+ if (handler != null) handler(value);
+ if (changedEvent != null) changedEvent(this, value);
+ }
+ }
+
+ /// Holds static values for .
+ /// This avoids one static instance per type T.
+ internal static class ProgressStatics
+ {
+ /// A default synchronization context that targets the ThreadPool.
+ internal static readonly SynchronizationContext DefaultContext = new SynchronizationContext();
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Properties/AssemblyInfo.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..8c972199d
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Microsoft.Threading.Tasks")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("Microsoft.Threading.Tasks")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/AsyncServices.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/AsyncServices.cs
new file mode 100644
index 000000000..05651ad0f
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/AsyncServices.cs
@@ -0,0 +1,71 @@
+// NOTE: If you change this copy, please also change the copy under the BCL partition
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace System.Runtime.CompilerServices
+{
+ internal static class AsyncServices
+ {
+ /// Throws the exception on the ThreadPool.
+ /// The exception to propagate.
+ /// The target context on which to propagate the exception. Null to use the ThreadPool.
+ internal static void ThrowAsync(Exception exception, SynchronizationContext targetContext)
+ {
+ // If the user supplied a SynchronizationContext...
+ if (targetContext != null)
+ {
+ try
+ {
+ // Post the throwing of the exception to that context, and return.
+ targetContext.Post(state => { throw PrepareExceptionForRethrow((Exception)state); }, exception);
+ return;
+ }
+ catch (Exception postException)
+ {
+ // If something goes horribly wrong in the Post, we'll
+ // propagate both exceptions on the ThreadPool
+ exception = new AggregateException(exception, postException);
+ }
+ }
+
+ // Propagate the exception(s) on the ThreadPool
+ ThreadPool.QueueUserWorkItem(state => { throw PrepareExceptionForRethrow((Exception)state); }, exception);
+ }
+
+ /// Copies the exception's stack trace so its stack trace isn't overwritten.
+ /// The exception to prepare.
+ internal static Exception PrepareExceptionForRethrow(Exception exc)
+ {
+#if EXCEPTION_STACK_PRESERVE
+ Contract.Assume(exc != null);
+ if (s_prepForRemoting != null)
+ {
+ try { s_prepForRemoting.Invoke(exc, s_emptyParams); }
+ catch { }
+ }
+#endif
+ return exc;
+ }
+
+#if EXCEPTION_STACK_PRESERVE
+ /// A MethodInfo for the Exception.PrepForRemoting method.
+ private readonly static MethodInfo s_prepForRemoting = GetPrepForRemotingMethodInfo();
+ /// An empty array to use with MethodInfo.Invoke.
+ private readonly static Object[] s_emptyParams = new object[0];
+
+ /// Gets the MethodInfo for the internal PrepForRemoting method on Exception.
+ /// The MethodInfo if it could be retrieved, or else null.
+ private static MethodInfo GetPrepForRemotingMethodInfo()
+ {
+ try
+ {
+ return typeof(Exception).GetMethod("PrepForRemoting", BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+ catch { return null; }
+ }
+#endif
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/ConfiguredTaskAwaitable.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/ConfiguredTaskAwaitable.cs
new file mode 100644
index 000000000..1634eb9a9
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/ConfiguredTaskAwaitable.cs
@@ -0,0 +1,104 @@
+// NOTE: The reason this type does exist in the BCL System.Threading.Tasks contract is because we need to be able to construct one of these in the AwaitExtensions
+// class. The equivalent type in the current platform does not have an accessible constructor, hence the AwaitExtensions would fail when run on platforms
+// where System.Threading.Tasks gets unified.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.Runtime.CompilerServices
+{
+ /// Provides an awaitable object that allows for configured awaits on .
+ /// This type is intended for compiler use only.
+ public struct ConfiguredTaskAwaitable
+ {
+ /// The task being awaited.
+ private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter;
+
+ /// Initializes the .
+ /// The awaitable .
+ ///
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ ///
+ internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext)
+ {
+ Contract.Assert(task != null);
+ m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext);
+ }
+
+ /// Gets an awaiter for this awaitable.
+ /// The awaiter.
+ public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter()
+ {
+ return m_configuredTaskAwaiter;
+ }
+
+ /// Provides an awaiter for a .
+ /// This type is intended for compiler use only.
+ public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// The task being awaited.
+ private readonly Task m_task;
+ /// Whether to attempt marshaling back to the original context.
+ private readonly bool m_continueOnCapturedContext;
+
+ /// Initializes the .
+ /// The to await.
+ ///
+ /// true to attempt to marshal the continuation back to the original context captured
+ /// when BeginAwait is called; otherwise, false.
+ ///
+ internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext)
+ {
+ Contract.Assert(task != null);
+ m_task = task;
+ m_continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// Gets whether the task being awaited is completed.
+ /// This property is intended for compiler user rather than use directly in code.
+ /// The awaiter was not properly initialized.
+ public bool IsCompleted { get { return m_task.IsCompleted; } }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext);
+ }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+#if !SILVERLIGHT
+ // [SecurityCritical]
+#endif
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext);
+ }
+
+ /// Ends the await on the completed .
+ /// The result of the completed .
+ /// The awaiter was not properly initialized.
+ /// The task was not yet completed.
+ /// The task was canceled.
+ /// The task completed in a Faulted state.
+ public void GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ }
+ }
+ }
+
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/ConfiguredTaskAwaitableOfTResult.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/ConfiguredTaskAwaitableOfTResult.cs
new file mode 100644
index 000000000..a894eba0e
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/ConfiguredTaskAwaitableOfTResult.cs
@@ -0,0 +1,100 @@
+// NOTE: The reason this type does exist in the BCL System.Threading.Tasks contract is because we need to be able to construct one of these in the AwaitExtensions
+// class. The equivalent type in the current platform does not have an accessible constructor, hence the AwaitExtensions would fail when run on platforms
+// where System.Threading.Tasks gets unified.
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace Microsoft.Runtime.CompilerServices
+{
+ /// Provides an awaitable object that allows for configured awaits on .
+ /// This type is intended for compiler use only.
+ public struct ConfiguredTaskAwaitable
+ {
+ /// The underlying awaitable on whose logic this awaitable relies.
+ private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter;
+
+ /// Initializes the .
+ /// The awaitable .
+ ///
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ ///
+ internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext)
+ {
+ m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext);
+ }
+
+ /// Gets an awaiter for this awaitable.
+ /// The awaiter.
+ public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter()
+ {
+ return m_configuredTaskAwaiter;
+ }
+
+ /// Provides an awaiter for a .
+ /// This type is intended for compiler use only.
+ public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// The task being awaited.
+ private readonly Task m_task;
+ /// Whether to attempt marshaling back to the original context.
+ private readonly bool m_continueOnCapturedContext;
+
+ /// Initializes the .
+ /// The awaitable .
+ ///
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ ///
+ internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext)
+ {
+ Contract.Assert(task != null);
+ m_task = task;
+ m_continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// Gets whether the task being awaited is completed.
+ /// This property is intended for compiler user rather than use directly in code.
+ /// The awaiter was not properly initialized.
+ public bool IsCompleted { get { return m_task.IsCompleted; } }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext);
+ }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+#if !SILVERLIGHT
+ // [SecurityCritical]
+#endif
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext);
+ }
+
+ /// Ends the await on the completed .
+ /// The result of the completed .
+ /// The awaiter was not properly initialized.
+ /// The task was not yet completed.
+ /// The task was canceled.
+ /// The task completed in a Faulted state.
+ public TResult GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ return m_task.Result;
+ }
+ }
+
+ }
+
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/TaskAwaiter.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/TaskAwaiter.cs
new file mode 100644
index 000000000..713d60b60
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/TaskAwaiter.cs
@@ -0,0 +1,235 @@
+// NOTE: The reason this type does exist in the BCL System.Threading.Tasks contract is because we need to be able to construct one of these in the AwaitExtensions
+// class. The equivalent type in the current platform does not have an accessible constructor, hence the AwaitExtensions would fail when run on platforms
+// where System.Threading.Tasks gets unified.
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Microsoft.Runtime.CompilerServices
+{
+ /// Provides an awaiter for awaiting a .
+ /// This type is intended for compiler use only.
+ public struct TaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// The default value to use for continueOnCapturedContext.
+ internal const bool CONTINUE_ON_CAPTURED_CONTEXT_DEFAULT = true; // marshal by default
+ /// The task being awaited.
+ private readonly Task m_task;
+
+ /// Initializes the .
+ /// The to be awaited.
+ internal TaskAwaiter(Task task)
+ {
+ Contract.Assert(task != null);
+ m_task = task;
+ }
+
+ /// Gets whether the task being awaited is completed.
+ /// This property is intended for compiler user rather than use directly in code.
+ /// The awaiter was not properly initialized.
+ public bool IsCompleted { get { return m_task.IsCompleted; } }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+ public void OnCompleted(Action continuation)
+ {
+ OnCompletedInternal(m_task, continuation, CONTINUE_ON_CAPTURED_CONTEXT_DEFAULT);
+ }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+#if !SILVERLIGHT
+ // [SecurityCritical]
+#endif
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ OnCompletedInternal(m_task, continuation, CONTINUE_ON_CAPTURED_CONTEXT_DEFAULT);
+ }
+
+ /// Ends the await on the completed .
+ /// The awaiter was not properly initialized.
+ /// The task was not yet completed.
+ /// The task was canceled.
+ /// The task completed in a Faulted state.
+ public void GetResult()
+ {
+ ValidateEnd(m_task);
+ }
+
+ ///
+ /// Fast checks for the end of an await operation to determine whether more needs to be done
+ /// prior to completing the await.
+ ///
+ /// The awaited task.
+ internal static void ValidateEnd(Task task)
+ {
+ if (task.Status != TaskStatus.RanToCompletion)
+ HandleNonSuccess(task);
+ }
+
+ /// Handles validations on tasks that aren't successfully completed.
+ /// The awaited task.
+ private static void HandleNonSuccess(Task task)
+ {
+ if (!task.IsCompleted)
+ {
+ try { task.Wait(); }
+ catch { }
+ }
+ if (task.Status != TaskStatus.RanToCompletion)
+ {
+ ThrowForNonSuccess(task);
+ }
+ }
+
+ /// Throws an exception to handle a task that completed in a state other than RanToCompletion.
+ private static void ThrowForNonSuccess(Task task)
+ {
+ Contract.Assert(task.Status != TaskStatus.RanToCompletion);
+
+ // Handle whether the task has been canceled or faulted
+ switch (task.Status)
+ {
+ // If the task completed in a canceled state, throw an OperationCanceledException.
+ // TaskCanceledException derives from OCE, and by throwing it we automatically pick up the
+ // completed task's CancellationToken if it has one, including that CT in the OCE.
+ case TaskStatus.Canceled:
+ throw new TaskCanceledException(task);
+
+ // If the task faulted, throw its first exception,
+ // even if it contained more than one.
+ case TaskStatus.Faulted:
+ throw PrepareExceptionForRethrow(task.Exception.InnerException);
+
+ // This should not happen on valid usage.
+ default:
+ throw new InvalidOperationException(InvalidOperationException_TaskNotCompleted);
+ }
+ }
+
+ /// Error message for GetAwaiter.
+ private const string InvalidOperationException_TaskNotCompleted = "The task has not yet completed.";
+
+ /// Schedules the continuation onto the associated with this .
+ /// The awaited task.
+ /// The action to invoke when the await operation completes.
+ /// Whether to capture and marshal back to the current context.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+ internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext)
+ {
+ if (continuation == null) throw new ArgumentNullException("continuation");
+ SynchronizationContext sc = continueOnCapturedContext ? SynchronizationContext.Current : null;
+ if (sc != null && sc.GetType() != typeof(SynchronizationContext))
+ {
+ // When the task completes, post to the synchronization context, or run it inline if we're already in the right place
+ task.ContinueWith(delegate
+ {
+ try { sc.Post(state => ((Action)state)(), continuation); }
+ catch (Exception exc) { AsyncServices.ThrowAsync(exc, null); }
+ }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+ else
+ {
+ var scheduler = continueOnCapturedContext ? TaskScheduler.Current : TaskScheduler.Default;
+ if (task.IsCompleted)
+ {
+ Task.Factory.StartNew(
+ s => ((Action)s)(), continuation, CancellationToken.None, TaskCreationOptions.None, scheduler);
+ }
+ else
+ {
+ // NOTE: There is a known rare race here. For performance reasons, we want this continuation to
+ // execute synchronously when the task completes, but if the task is already completed by the time
+ // we call ContinueWith, we don't want it executing synchronously as part of the ContinueWith call.
+ // If the race occurs, and if the unbelievable happens and it occurs frequently enough to
+ // stack dive, ContinueWith's support for depth checking helps to mitigate this.
+
+ if (scheduler != TaskScheduler.Default)
+ {
+ // When the task completes, run the continuation in a callback using the correct task scheduler.
+ task.ContinueWith(_ => RunNoException(continuation),
+ CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
+ }
+ else
+ {
+ // When the task completes, run the continuation in a callback using the correct task scheduler.
+ task.ContinueWith(delegate
+ {
+ if (IsValidLocationForInlining)
+ RunNoException(continuation);
+ else
+ Task.Factory.StartNew(s => RunNoException((Action)s),
+ continuation, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
+ }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+ }
+ }
+ }
+
+ /// Invokes the delegate in a try/catch that will propagate the exception asynchronously on the ThreadPool.
+ ///
+ private static void RunNoException(Action continuation)
+ {
+ try { continuation(); }
+ catch (Exception exc) { AsyncServices.ThrowAsync(exc, null); }
+ }
+
+ /// Whether the current thread is appropriate for inlining the await continuation.
+ private static bool IsValidLocationForInlining
+ {
+ get
+ {
+ var currentCtx = SynchronizationContext.Current;
+ if (currentCtx != null && currentCtx.GetType() != typeof(SynchronizationContext))
+ return false;
+ else
+ return TaskScheduler.Current == TaskScheduler.Default;
+ }
+ }
+
+ /// Copies the exception's stack trace so its stack trace isn't overwritten.
+ /// The exception to prepare.
+ internal static Exception PrepareExceptionForRethrow(Exception exc)
+ {
+#if EXCEPTION_STACK_PRESERVE
+ Contract.Assume(exc != null);
+ if (s_prepForRemoting != null)
+ {
+ try { s_prepForRemoting.Invoke(exc, s_emptyParams); }
+ catch { }
+ }
+#endif
+ return exc;
+ }
+
+#if EXCEPTION_STACK_PRESERVE
+ /// A MethodInfo for the Exception.PrepForRemoting method.
+ private readonly static MethodInfo s_prepForRemoting = GetPrepForRemotingMethodInfo();
+ /// An empty array to use with MethodInfo.Invoke.
+ private readonly static Object[] s_emptyParams = new object[0];
+
+ /// Gets the MethodInfo for the internal PrepForRemoting method on Exception.
+ /// The MethodInfo if it could be retrieved, or else null.
+ private static MethodInfo GetPrepForRemotingMethodInfo()
+ {
+ try
+ {
+ return typeof(Exception).GetMethod("PrepForRemoting", BindingFlags.NonPublic | BindingFlags.Instance);
+ }
+ catch { return null; }
+ }
+#endif
+ }
+
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/TaskAwaiterOfTResult.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/TaskAwaiterOfTResult.cs
new file mode 100644
index 000000000..752a7c4d5
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/TaskAwaiterOfTResult.cs
@@ -0,0 +1,68 @@
+// NOTE: The reason this type does exist in the BCL System.Threading.Tasks contract is because we need to be able to construct one of these in the AwaitExtensions
+// class. The equivalent type in the current platform does not have an accessible constructor, hence the AwaitExtensions would fail when run on platforms
+// where System.Threading.Tasks gets unified.
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace Microsoft.Runtime.CompilerServices
+{
+ /// Provides an awaiter for awaiting a .
+ /// This type is intended for compiler use only.
+ public struct TaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// The task being awaited.
+ private readonly Task m_task;
+
+ /// Initializes the .
+ /// The to be awaited.
+ internal TaskAwaiter(Task task)
+ {
+ Contract.Assert(task != null);
+ m_task = task;
+ }
+
+ /// Gets whether the task being awaited is completed.
+ /// This property is intended for compiler user rather than use directly in code.
+ /// The awaiter was not properly initialized.
+ public bool IsCompleted { get { return m_task.IsCompleted; } }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, TaskAwaiter.CONTINUE_ON_CAPTURED_CONTEXT_DEFAULT);
+ }
+
+ /// Schedules the continuation onto the associated with this .
+ /// The action to invoke when the await operation completes.
+ /// The argument is null (Nothing in Visual Basic).
+ /// The awaiter was not properly initialized.
+ /// This method is intended for compiler user rather than use directly in code.
+#if !SILVERLIGHT
+ //[SecurityCritical]
+#endif
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, TaskAwaiter.CONTINUE_ON_CAPTURED_CONTEXT_DEFAULT);
+ }
+
+ /// Ends the await on the completed .
+ /// The result of the completed .
+ /// The awaiter was not properly initialized.
+ /// The task was not yet completed.
+ /// The task was canceled.
+ /// The task completed in a Faulted state.
+ public TResult GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ return m_task.Result;
+ }
+ }
+
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/YieldAwaitable.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/YieldAwaitable.cs
new file mode 100644
index 000000000..4f0a0dbc3
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Runtime/CompilerServices/YieldAwaitable.cs
@@ -0,0 +1,46 @@
+// NOTE: The reason this type does exist in the BCL System.Threading.Tasks contract is because we need to be able to construct one of these in the AwaitExtensions
+// class. The equivalent type in the current platform does not have an accessible constructor, hence the AwaitExtensions would fail when run on platforms
+// where System.Threading.Tasks gets unified.
+using System;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace Microsoft.Runtime.CompilerServices
+{
+ /// Provides an awaitable context for switching into a target environment.
+ /// This type is intended for compiler use only.
+ public struct YieldAwaitable
+ {
+ /// Gets an awaiter for this .
+ /// An awaiter for this awaitable.
+ /// This method is intended for compiler user rather than use directly in code.
+ public YieldAwaiter GetAwaiter() { return new YieldAwaiter(); } // if not initialized properly, m_target will just be null
+
+ /// Provides an awaiter that switches into a target environment.
+ /// This type is intended for compiler use only.
+ public struct YieldAwaiter : ICriticalNotifyCompletion
+ {
+ /// A completed task.
+ private readonly static Task s_completed = TaskEx.FromResult(0);
+
+ /// Gets whether a yield is not required.
+ /// This property is intended for compiler user rather than use directly in code.
+ public bool IsCompleted { get { return false; } } // yielding is always required for YieldAwaiter, hence false
+
+ /// Posts the back to the current context.
+ /// The action to invoke asynchronously.
+ /// The awaiter was not properly initialized.
+ public void OnCompleted(Action continuation) { s_completed.GetAwaiter().OnCompleted(continuation); }
+
+ /// Posts the back to the current context.
+ /// The action to invoke asynchronously.
+ /// The awaiter was not properly initialized.
+ //[SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation) { s_completed.GetAwaiter().UnsafeOnCompleted(continuation); }
+
+ /// Ends the await operation.
+ public void GetResult() { } // Nop. It exists purely because the compiler pattern demands it.
+ }
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/Tasks/TaskEx.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/Tasks/TaskEx.cs
new file mode 100644
index 000000000..3061f44c4
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/Tasks/TaskEx.cs
@@ -0,0 +1,434 @@
+using Microsoft.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Linq;
+
+namespace System.Threading.Tasks
+{
+ /// Provides methods for creating and manipulating tasks.
+ public static class TaskEx
+ {
+ #region Run
+ /// Creates a task that runs the specified action.
+ /// The action to execute asynchronously.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Action action)
+ {
+ return Run(action, CancellationToken.None);
+ }
+
+ /// Creates a task that runs the specified action.
+ /// The action to execute.
+ /// The CancellationToken to use to request cancellation of this task.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Action action, CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(action, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Creates a task that runs the specified function.
+ /// The function to execute asynchronously.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Func function)
+ {
+ return Run(function, CancellationToken.None);
+ }
+
+ /// Creates a task that runs the specified function.
+ /// The action to execute.
+ /// The CancellationToken to use to cancel the task.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Func function, CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(function, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);
+ }
+
+ /// Creates a task that runs the specified function.
+ /// The action to execute asynchronously.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Func function)
+ {
+ return Run(function, CancellationToken.None);
+ }
+
+ /// Creates a task that runs the specified function.
+ /// The function to execute.
+ /// The CancellationToken to use to request cancellation of this task.
+ /// A task that represents the completion of the function.
+ /// The argument is null.
+ public static Task Run(Func function, CancellationToken cancellationToken)
+ {
+ return Run(function, cancellationToken).Unwrap();
+ }
+
+ /// Creates a task that runs the specified function.
+ /// The function to execute asynchronously.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Func> function)
+ {
+ return Run(function, CancellationToken.None);
+ }
+
+ /// Creates a task that runs the specified function.
+ /// The action to execute.
+ /// The CancellationToken to use to cancel the task.
+ /// A task that represents the completion of the action.
+ /// The argument is null.
+ public static Task Run(Func> function, CancellationToken cancellationToken)
+ {
+ return Run>(function, cancellationToken).Unwrap();
+ }
+ #endregion
+
+ #region Delay
+ /// Starts a Task that will complete after the specified due time.
+ /// The delay in milliseconds before the returned task completes.
+ /// The timed Task.
+ ///
+ /// The argument must be non-negative or -1 and less than or equal to Int32.MaxValue.
+ ///
+ public static Task Delay(int dueTime)
+ {
+ return Delay(dueTime, CancellationToken.None);
+ }
+
+ /// Starts a Task that will complete after the specified due time.
+ /// The delay before the returned task completes.
+ /// The timed Task.
+ ///
+ /// The argument must be non-negative or -1 and less than or equal to Int32.MaxValue.
+ ///
+ public static Task Delay(TimeSpan dueTime)
+ {
+ return Delay(dueTime, CancellationToken.None);
+ }
+
+ /// Starts a Task that will complete after the specified due time.
+ /// The delay before the returned task completes.
+ /// A CancellationToken that may be used to cancel the task before the due time occurs.
+ /// The timed Task.
+ ///
+ /// The argument must be non-negative or -1 and less than or equal to Int32.MaxValue.
+ ///
+ public static Task Delay(TimeSpan dueTime, CancellationToken cancellationToken)
+ {
+ long totalMilliseconds = (long)dueTime.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue) throw new ArgumentOutOfRangeException("dueTime", ArgumentOutOfRange_TimeoutNonNegativeOrMinusOne);
+ Contract.EndContractBlock();
+ return Delay((int)totalMilliseconds, cancellationToken);
+ }
+
+
+
+ /// Starts a Task that will complete after the specified due time.
+ /// The delay in milliseconds before the returned task completes.
+ /// A CancellationToken that may be used to cancel the task before the due time occurs.
+ /// The timed Task.
+ ///
+ /// The argument must be non-negative or -1 and less than or equal to Int32.MaxValue.
+ ///
+ public static Task Delay(int dueTime, CancellationToken cancellationToken)
+ {
+ // Validate arguments
+ if (dueTime < -1) throw new ArgumentOutOfRangeException("dueTime", ArgumentOutOfRange_TimeoutNonNegativeOrMinusOne);
+ Contract.EndContractBlock();
+
+ // Fast-paths if the timeout has expired or the token has had cancellation requested
+ if (cancellationToken.IsCancellationRequested) return new Task(() => { }, cancellationToken);
+ if (dueTime == 0) return s_preCompletedTask;
+
+ // Create the timed task
+ var tcs = new TaskCompletionSource();
+ var ctr = default(CancellationTokenRegistration);
+
+ Timer timer = null;
+ // Create the timer but don't start it yet. If we start it now,
+ // it might fire before ctr has been set to the right registration.
+ timer = new Timer(state =>
+ {
+ // Clean up both the cancellation token and the timer, and try to transition to completed
+ ctr.Dispose();
+ timer.Dispose();
+ tcs.TrySetResult(true);
+
+ TimerManager.Remove(timer);
+
+ }, null, Timeout.Infinite, Timeout.Infinite);
+
+ // Make sure the timer stays rooted. The full Framework
+ // does this automatically when constructing a timer with the simple
+ // overload that doesn't take state, in which case the timer itself
+ // is the state. But Compact Framework doesn't root, so we need to.
+ TimerManager.Add(timer);
+
+ // Register with the cancellation token if a cancelable one was provided. This must be
+ // done after initializing timer, as we call timer.Dispose from within the callback
+ // and that callback will fire synchronously if the token has already been canceled
+ // by the time we call Register.
+ if (cancellationToken.CanBeCanceled)
+ {
+ // When cancellation occurs, cancel the timer and try to transition to canceled.
+ // There could be a race, but it's benign.
+ ctr = cancellationToken.Register(() =>
+ {
+ timer.Dispose();
+ tcs.TrySetCanceled();
+ TimerManager.Remove(timer);
+ });
+ }
+
+ // Start the timer and hand back the task...
+ timer.Change(dueTime, Timeout.Infinite);
+ return tcs.Task;
+ }
+
+ private const string ArgumentOutOfRange_TimeoutNonNegativeOrMinusOne = "The timeout must be non-negative or -1, and it must be less than or equal to Int32.MaxValue.";
+
+ /// An already completed task.
+ private static Task s_preCompletedTask = TaskEx.FromResult(false);
+ #endregion
+
+ #region WhenAll
+ /// Creates a Task that will complete only when all of the provided collection of Tasks has completed.
+ /// The Tasks to monitor for completion.
+ /// A Task that represents the completion of all of the provided tasks.
+ ///
+ /// If any of the provided Tasks faults, the returned Task will also fault, and its Exception will contain information
+ /// about all of the faulted tasks. If no Tasks fault but one or more Tasks is canceled, the returned
+ /// Task will also be canceled.
+ ///
+ /// The argument is null.
+ /// The argument contains a null reference.
+ public static Task WhenAll(params Task[] tasks)
+ {
+ return WhenAll((IEnumerable)tasks);
+ }
+
+ /// Creates a Task that will complete only when all of the provided collection of Tasks has completed.
+ /// The Tasks to monitor for completion.
+ /// A Task that represents the completion of all of the provided tasks.
+ ///
+ /// If any of the provided Tasks faults, the returned Task will also fault, and its Exception will contain information
+ /// about all of the faulted tasks. If no Tasks fault but one or more Tasks is canceled, the returned
+ /// Task will also be canceled.
+ ///
+ /// The argument is null.
+ /// The argument contains a null reference.
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
+ public static Task WhenAll(params Task[] tasks)
+ {
+ return WhenAll((IEnumerable>)tasks);
+ }
+
+ /// Creates a Task that will complete only when all of the provided collection of Tasks has completed.
+ /// The Tasks to monitor for completion.
+ /// A Task that represents the completion of all of the provided tasks.
+ ///
+ /// If any of the provided Tasks faults, the returned Task will also fault, and its Exception will contain information
+ /// about all of the faulted tasks. If no Tasks fault but one or more Tasks is canceled, the returned
+ /// Task will also be canceled.
+ ///
+ /// The argument is null.
+ /// The argument contains a null reference.
+ public static Task WhenAll(IEnumerable tasks)
+ {
+ return WhenAllCore(tasks, (completedTasks, tcs) =>
+ tcs.TrySetResult(null));
+ }
+
+ /// Creates a Task that will complete only when all of the provided collection of Tasks has completed.
+ /// The Tasks to monitor for completion.
+ /// A Task that represents the completion of all of the provided tasks.
+ ///
+ /// If any of the provided Tasks faults, the returned Task will also fault, and its Exception will contain information
+ /// about all of the faulted tasks. If no Tasks fault but one or more Tasks is canceled, the returned
+ /// Task will also be canceled.
+ ///
+ /// The argument is null.
+ /// The argument contains a null reference.
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
+ public static Task WhenAll(IEnumerable> tasks)
+ {
+ return WhenAllCore(tasks.Cast(), (completedTasks, tcs) =>
+ tcs.TrySetResult(completedTasks.Select(t => ((Task)t).Result).ToArray()));
+ }
+
+ /// Creates a Task that will complete only when all of the provided collection of Tasks has completed.
+ /// The Tasks to monitor for completion.
+ ///
+ /// A callback invoked when all of the tasks complete successfully in the RanToCompletion state.
+ /// This callback is responsible for storing the results into the TaskCompletionSource.
+ ///
+ /// A Task that represents the completion of all of the provided tasks.
+ /// The argument is null.
+ /// The argument contains a null reference.
+ private static Task WhenAllCore(
+ IEnumerable tasks,
+ Action> setResultAction)
+ {
+ // Validate arguments
+ if (tasks == null) throw new ArgumentNullException("tasks");
+ Contract.EndContractBlock();
+ Contract.Assert(setResultAction != null);
+
+ // Create a TCS to represent the completion of all of the tasks. This TCS's Task is
+ // completed by a ContinueWhenAll continuation
+ var tcs = new TaskCompletionSource();
+ var taskArr = tasks as Task[] ?? tasks.ToArray();
+ if (taskArr.Length == 0)
+ {
+ setResultAction(taskArr, tcs);
+ }
+ else
+ {
+ Task.Factory.ContinueWhenAll(taskArr, completedTasks =>
+ {
+ // Get exceptions for any faulted or canceled tasks
+ List exceptions = null;
+ bool canceled = false;
+ foreach (var task in completedTasks)
+ {
+ if (task.IsFaulted) AddPotentiallyUnwrappedExceptions(ref exceptions, task.Exception);
+ else if (task.IsCanceled) canceled = true;
+ }
+
+ // Set up the resulting task.
+ if (exceptions != null && exceptions.Count > 0) tcs.TrySetException(exceptions);
+ else if (canceled) tcs.TrySetCanceled();
+ else setResultAction(completedTasks, tcs);
+ }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+
+ // Return the resulting task
+ return tcs.Task;
+ }
+ #endregion
+
+ #region WhenAny
+ /// Creates a Task that will complete when any of the tasks in the provided collection completes.
+ /// The Tasks to be monitored.
+ ///
+ /// A Task that represents the completion of any of the provided Tasks. The completed Task is this Task's result.
+ ///
+ /// Any Tasks that fault will need to have their exceptions observed elsewhere.
+ /// The argument is null.
+ /// The argument contains a null reference.
+ public static Task WhenAny(params Task[] tasks)
+ {
+ return WhenAny((IEnumerable)tasks);
+ }
+
+ /// Creates a Task that will complete when any of the tasks in the provided collection completes.
+ /// The Tasks to be monitored.
+ ///
+ /// A Task that represents the completion of any of the provided Tasks. The completed Task is this Task's result.
+ ///
+ /// Any Tasks that fault will need to have their exceptions observed elsewhere.
+ /// The argument is null.
+ /// The argument contains a null reference.
+ public static Task WhenAny(IEnumerable tasks)
+ {
+ // Validate arguments
+ if (tasks == null) throw new ArgumentNullException("tasks");
+ Contract.EndContractBlock();
+
+ // Create a task that will complete with
+ var tcs = new TaskCompletionSource();
+ Task.Factory.ContinueWhenAny(tasks as Task[] ?? tasks.ToArray(),
+ completed => tcs.TrySetResult(completed),
+ CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ return tcs.Task;
+ }
+
+ /// Creates a Task that will complete when any of the tasks in the provided collection completes.
+ /// The Tasks to be monitored.
+ ///
+ /// A Task that represents the completion of any of the provided Tasks. The completed Task is this Task's result.
+ ///
+ /// Any Tasks that fault will need to have their exceptions observed elsewhere.
+ /// The argument is null.
+ /// The argument contains a null reference.
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
+ public static Task> WhenAny(params Task[] tasks)
+ {
+ return WhenAny((IEnumerable>)tasks);
+ }
+
+ /// Creates a Task that will complete when any of the tasks in the provided collection completes.
+ /// The Tasks to be monitored.
+ ///
+ /// A Task that represents the completion of any of the provided Tasks. The completed Task is this Task's result.
+ ///
+ /// Any Tasks that fault will need to have their exceptions observed elsewhere.
+ /// The argument is null.
+ /// The argument contains a null reference.
+ [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
+ public static Task> WhenAny(IEnumerable> tasks)
+ {
+ // Validate arguments
+ if (tasks == null) throw new ArgumentNullException("tasks");
+ Contract.EndContractBlock();
+
+ // Create a task that will complete with
+ var tcs = new TaskCompletionSource>();
+ Task.Factory.ContinueWhenAny(tasks as Task[] ?? tasks.ToArray(),
+ completed => tcs.TrySetResult(completed),
+ CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ return tcs.Task;
+ }
+ #endregion
+
+ #region FromResult
+ /// Creates an already completed from the specified result.
+ /// The result from which to create the completed task.
+ /// The completed task.
+ public static Task FromResult(TResult result)
+ {
+ var tcs = new TaskCompletionSource(result);
+ tcs.TrySetResult(result);
+ return tcs.Task;
+ }
+ #endregion
+
+ #region Yield
+ /// Creates an awaitable that asynchronously yields back to the current context when awaited.
+ ///
+ /// A context that, when awaited, will asynchronously transition back into the current context.
+ /// If SynchronizationContext.Current is non-null, that is treated as the current context.
+ /// Otherwise, TaskScheduler.Current is treated as the current context.
+ ///
+ public static YieldAwaitable Yield() { return new YieldAwaitable(); }
+ #endregion
+
+ #region Private Helpers
+ /// Adds the target exception to the list, initializing the list if it's null.
+ /// The list to which to add the exception and initialize if the list is null.
+ /// The exception to add, and unwrap if it's an aggregate.
+ private static void AddPotentiallyUnwrappedExceptions(ref List targetList, Exception exception)
+ {
+ var ae = exception as AggregateException;
+
+ Contract.Assert(exception != null);
+ Contract.Assert(ae == null || ae.InnerExceptions.Count > 0);
+
+ // Initialize the list if necessary
+ if (targetList == null) targetList = new List();
+
+ // If the exception is an aggregate and it contains only one exception, add just its inner exception
+ if (ae != null)
+ {
+ targetList.Add(ae.InnerExceptions.Count == 1 ? exception.InnerException : exception);
+ }
+ // Otherwise, add the exception
+ else targetList.Add(exception);
+ }
+ #endregion
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/Tasks/TaskServices.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/Tasks/TaskServices.cs
new file mode 100644
index 000000000..1020bb2e2
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/Tasks/TaskServices.cs
@@ -0,0 +1,54 @@
+using System.ComponentModel;
+
+namespace System.Threading.Tasks
+{
+ internal class TaskServices
+ {
+ /// Returns a canceled task.
+ /// The cancellation token.
+ /// The canceled task.
+ public static Task FromCancellation(System.Threading.CancellationToken cancellationToken)
+ {
+ if (!cancellationToken.IsCancellationRequested) throw new System.ArgumentOutOfRangeException("cancellationToken");
+ return new Task(() => { }, cancellationToken);
+ }
+
+ /// Returns a canceled task.
+ /// Specifies the type of the result.
+ /// The cancellation token.
+ /// The canceled task.
+ public static Task FromCancellation(System.Threading.CancellationToken cancellationToken)
+ {
+ if (!cancellationToken.IsCancellationRequested) throw new System.ArgumentOutOfRangeException("cancellationToken");
+ return new Task(() => default(TResult), cancellationToken);
+ }
+
+ ///
+ /// Completes the Task if the user state matches the TaskCompletionSource.
+ ///
+ /// Specifies the type of data returned by the Task.
+ /// The TaskCompletionSource.
+ /// The completion event arguments.
+ /// Whether we require the tcs to match the e.UserState.
+ /// A function that gets the result with which to complete the task.
+ /// An action used to unregister work when the operaiton completes.
+ public static void HandleEapCompletion(
+ TaskCompletionSource tcs, bool requireMatch, AsyncCompletedEventArgs e, Func getResult, Action unregisterHandler)
+ {
+ // Transfers the results from the AsyncCompletedEventArgs and getResult() to the
+ // TaskCompletionSource, but only AsyncCompletedEventArg's UserState matches the TCS
+ // (this check is important if the same WebClient is used for multiple, asynchronous
+ // operations concurrently). Also unregisters the handler to avoid a leak.
+ if (!requireMatch || e.UserState == tcs)
+ {
+ try { unregisterHandler(); }
+ finally
+ {
+ if (e.Cancelled) tcs.TrySetCanceled();
+ else if (e.Error != null) tcs.TrySetException(e.Error);
+ else tcs.TrySetResult(getResult());
+ }
+ }
+ }
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/TimerManager.cs b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/TimerManager.cs
new file mode 100644
index 000000000..eef2acd94
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/Threading/TimerManager.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace System.Threading
+{
+
+ // Workaround for the lack of rooting of timers on Compat Framework/Windows Phone
+ internal static class TimerManager
+ {
+#if NO_TIMER_ROOT
+ private static Dictionary s_rootedTimers = new Dictionary();
+#endif
+ public static void Add(Timer timer)
+ {
+#if NO_TIMER_ROOT
+ lock (s_rootedTimers)
+ {
+ s_rootedTimers.Add(timer, null);
+ }
+#endif
+ }
+
+ public static void Remove(Timer timer)
+ {
+#if NO_TIMER_ROOT
+ lock (s_rootedTimers)
+ {
+ s_rootedTimers.Remove(timer);
+ }
+#endif
+ }
+ }
+}
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/app.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/app.config
new file mode 100644
index 000000000..a6a2b7fa9
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/app.config
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/packages.config b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/packages.config
new file mode 100644
index 000000000..2384716da
--- /dev/null
+++ b/Microsoft.Bcl.Async/Microsoft.Threading.Tasks/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl/CodePlexKey.snk b/Microsoft.Bcl/CodePlexKey.snk
new file mode 100644
index 000000000..5d44ffe87
Binary files /dev/null and b/Microsoft.Bcl/CodePlexKey.snk differ
diff --git a/Microsoft.Bcl/System.IO.v1.5/Properties/AssemblyInfo.cs b/Microsoft.Bcl/System.IO.v1.5/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..eac78e0bd
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v1.5/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("System.IO")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("System.IO")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.IO.v1.5/Strings.Designer.cs b/Microsoft.Bcl/System.IO.v1.5/Strings.Designer.cs
new file mode 100644
index 000000000..426216571
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v1.5/Strings.Designer.cs
@@ -0,0 +1,72 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.18046
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace System {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Strings() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Strings", typeof(Strings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Found invalid data while decoding..
+ ///
+ internal static string GenericInvalidData {
+ get {
+ return ResourceManager.GetString("GenericInvalidData", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Microsoft.Bcl/System.IO.v1.5/Strings.resx b/Microsoft.Bcl/System.IO.v1.5/Strings.resx
new file mode 100644
index 000000000..36dc2620b
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v1.5/Strings.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Found invalid data while decoding.
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.IO.v1.5/System.IO.v1.5.csproj b/Microsoft.Bcl/System.IO.v1.5/System.IO.v1.5.csproj
new file mode 100644
index 000000000..c0c4ef1d5
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v1.5/System.IO.v1.5.csproj
@@ -0,0 +1,71 @@
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {E18239EC-7C12-4704-A089-8B619C44F4C6}
+ Library
+ Properties
+ System
+ System.IO
+ v4.0
+ Profile88
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SAK
+ SAK
+ SAK
+ SAK
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG
+ prompt
+ 4
+ bin\Debug\System.IO.xml
+ SecurityRules.ruleset
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ bin\Release\System.IO.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+ True
+ True
+ Strings.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ Strings.Designer.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.IO.v1.5/System/IO/InvalidDataException.cs b/Microsoft.Bcl/System.IO.v1.5/System/IO/InvalidDataException.cs
new file mode 100644
index 000000000..776201ed7
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v1.5/System/IO/InvalidDataException.cs
@@ -0,0 +1,34 @@
+namespace System.IO {
+
+ using System;
+
+ ///
+ /// The exception that is thrown when a data stream is in an invalid format.
+ ///
+ public sealed class InvalidDataException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InvalidDataException ()
+ : base(Strings.GenericInvalidData) {
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified error message.
+ ///
+ /// The error message that explains the reason for the exception.
+ public InvalidDataException (String message)
+ : base(message) {
+ }
+
+ ///
+ /// Initializes a new instance of the class with a reference to the inner exception that is the cause of this exception.
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception. If the parameter is not null, the current exception is raised in a catch block that handles the inner exception.
+ public InvalidDataException (String message, Exception innerException)
+ : base(message, innerException) {
+ }
+
+ }
+}
diff --git a/Microsoft.Bcl/System.IO.v2.5/Properties/AssemblyInfo.cs b/Microsoft.Bcl/System.IO.v2.5/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..f9834b34b
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v2.5/Properties/AssemblyInfo.cs
@@ -0,0 +1,24 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Runtime.CompilerServices;
+using System.IO;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("System.IO")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("System.IO")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+
+[assembly: TypeForwardedTo(typeof(InvalidDataException))]
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.IO.v2.5/System.IO.v2.5.csproj b/Microsoft.Bcl/System.IO.v2.5/System.IO.v2.5.csproj
new file mode 100644
index 000000000..f426f1bb9
--- /dev/null
+++ b/Microsoft.Bcl/System.IO.v2.5/System.IO.v2.5.csproj
@@ -0,0 +1,59 @@
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {BD52BEC2-B8A9-4C12-968B-87E9D77776DA}
+ Library
+ Properties
+ System
+ System.IO
+ v4.0
+ Profile5
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SAK
+ SAK
+ SAK
+ SAK
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG
+ prompt
+ 4
+ bin\Debug\System.IO.xml
+ SecurityRules.ruleset
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ bin\Release\System.IO.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/Properties/AssemblyInfo.cs b/Microsoft.Bcl/System.Runtime.v1.5/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..a2253d6b0
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("System.Runtime")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyProduct("System.Runtime")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/Strings.Designer.cs b/Microsoft.Bcl/System.Runtime.v1.5/Strings.Designer.cs
new file mode 100644
index 000000000..4ef234b98
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/Strings.Designer.cs
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.17929
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace System {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Strings() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Strings", typeof(Strings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Argument must be of type {0}..
+ ///
+ internal static string ArgumentException_TupleIncorrectType {
+ get {
+ return ResourceManager.GetString("ArgumentException_TupleIncorrectType", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The last element of an eight element tuple must be a Tuple..
+ ///
+ internal static string ArgumentException_TupleLastArgumentNotATuple {
+ get {
+ return ResourceManager.GetString("ArgumentException_TupleLastArgumentNotATuple", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/Strings.resx b/Microsoft.Bcl/System.Runtime.v1.5/Strings.resx
new file mode 100644
index 000000000..4c671ff08
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/Strings.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Argument must be of type {0}.
+
+
+ The last element of an eight element tuple must be a Tuple.
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System.Runtime.v1.5.csproj b/Microsoft.Bcl/System.Runtime.v1.5/System.Runtime.v1.5.csproj
new file mode 100644
index 000000000..70e845671
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System.Runtime.v1.5.csproj
@@ -0,0 +1,79 @@
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {42DB1993-8EBB-4827-BC05-F3906EA8CFBC}
+ Library
+ Properties
+ System
+ System.Runtime
+ v4.0
+ Profile88
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SAK
+ SAK
+ SAK
+ SAK
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG
+ prompt
+ 4
+ bin\Debug\System.Runtime.xml
+ SecurityRules.ruleset
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ bin\Release\System.Runtime.xml
+
+
+ true
+ true
+ ..\CodePlexKey.snk
+
+
+
+
+ True
+ True
+ Strings.resx
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Strings.Designer.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System.Runtime.v1.5.csproj.vspscc b/Microsoft.Bcl/System.Runtime.v1.5/System.Runtime.v1.5.csproj.vspscc
new file mode 100644
index 000000000..b6d32892f
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System.Runtime.v1.5.csproj.vspscc
@@ -0,0 +1,10 @@
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Collections/IStructuralComparable.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Collections/IStructuralComparable.cs
new file mode 100644
index 000000000..6c6275e7f
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Collections/IStructuralComparable.cs
@@ -0,0 +1,29 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Collections
+{
+ ///
+ /// Supports the structural comparison of collection objects.
+ ///
+ public interface IStructuralComparable
+ {
+ ///
+ /// Determines whether the current collection object precedes, occurs in the same position as, or follows another object in the sort order.
+ ///
+ /// The object to compare with the current instance.
+ /// An object that compares members of the current collection object with the corresponding members of other.
+ /// An integer that indicates the relationship of the current collection object to other.
+ ///
+ /// This instance and other are not the same type.
+ ///
+ int CompareTo(object other, IComparer comparer);
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Collections/IStructuralEquatable.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Collections/IStructuralEquatable.cs
new file mode 100644
index 000000000..eeb8667ea
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Collections/IStructuralEquatable.cs
@@ -0,0 +1,33 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Collections
+{
+ ///
+ /// Defines methods to support the comparison of objects for structural equality.
+ ///
+ public interface IStructuralEquatable
+ {
+ ///
+ /// Determines whether an object is structurally equal to the current instance.
+ ///
+ /// The object to compare with the current instance.
+ /// An object that determines whether the current instance and other are equal.
+ /// true if the two objects are equal; otherwise, false.
+ bool Equals(object other, IEqualityComparer comparer);
+
+ ///
+ /// Returns a hash code for the current instance.
+ ///
+ /// An object that computes the hash code of the current object.
+ /// The hash code for the current instance.
+ int GetHashCode(IEqualityComparer comparer);
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Func.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Func.cs
new file mode 100644
index 000000000..84f21da7b
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Func.cs
@@ -0,0 +1,30 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace System
+{
+ ///
+ /// Encapsulates a method that has five parameters and returns a value of the type specified by the TResult parameter.
+ ///
+ /// The type of the first parameter of the method that this delegate encapsulates.
+ /// The type of the second parameter of the method that this delegate encapsulates.
+ /// The type of the third parameter of the method that this delegate encapsulates.
+ /// The type of the fourth parameter of the method that this delegate encapsulates.
+ /// The type of the fifth parameter of the method that this delegate encapsulates.
+ /// The type of the return value of the method that this delegate encapsulates.
+ /// The first parameter of the method that this delegate encapsulates.
+ /// The second parameter of the method that this delegate encapsulates.
+ /// The third parameter of the method that this delegate encapsulates.
+ /// The fourth parameter of the method that this delegate encapsulates.
+ /// The fifth parameter of the method that this delegate encapsulates.
+ /// The return value of the method that this delegate encapsulates.
+ public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Progress.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Progress.cs
new file mode 100644
index 000000000..2bc82e9a7
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Progress.cs
@@ -0,0 +1,28 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading;
+
+namespace System
+{
+ /// Defines a provider for progress updates.
+ /// The type of progress update value.
+#if VARIANCE
+ public interface IProgress
+#else
+ public interface IProgress
+#endif
+ {
+ /// Reports a progress update.
+ /// The value of the updated progress.
+ void Report(T value);
+ }
+}
\ No newline at end of file
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs
new file mode 100644
index 000000000..506804810
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs
@@ -0,0 +1,21 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace System.Runtime.CompilerServices
+{
+ /// Identities the async state machine type for this method.
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public sealed class AsyncStateMachineAttribute : StateMachineAttribute
+ {
+ /// Initializes the attribute.
+ /// The type that implements the state machine.
+ public AsyncStateMachineAttribute(Type stateMachineType) : base(stateMachineType) { }
+ }
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/CallerInfoAttributes.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/CallerInfoAttributes.cs
new file mode 100644
index 000000000..b5c7f8dfb
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/CallerInfoAttributes.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace System.Runtime.CompilerServices
+{
+ ///
+ /// Allows you to obtain the method or property name of the caller to the method.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class CallerMemberNameAttribute : Attribute { }
+
+ ///
+ /// Allows you to obtain the line number in the source file at which the method is called.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class CallerLineNumberAttribute : Attribute { }
+
+ ///
+ /// Allows you to obtain the full path of the source file that contains the caller.
+ /// This is the file path at the time of compile.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class CallerFilePathAttribute : Attribute { }
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs
new file mode 100644
index 000000000..92ad87638
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs
@@ -0,0 +1,22 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace System.Runtime.CompilerServices
+{
+ /// Identities the iterator state machine type for this method.
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public sealed class IteratorStateMachineAttribute : StateMachineAttribute
+ {
+ /// Initializes the attribute.
+ /// The type that implements the state machine.
+ public IteratorStateMachineAttribute(Type stateMachineType) : base(stateMachineType) { }
+ }
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/StateMachineAttribute.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/StateMachineAttribute.cs
new file mode 100644
index 000000000..6c4e5954a
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Runtime/CompilerServices/StateMachineAttribute.cs
@@ -0,0 +1,28 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace System.Runtime.CompilerServices
+{
+ /// Identities the state machine type for this method.
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public class StateMachineAttribute : Attribute
+ {
+ /// Initializes the attribute.
+ /// The type that implements the state machine.
+ public StateMachineAttribute(Type stateMachineType)
+ {
+ this.StateMachineType = stateMachineType;
+ }
+
+ /// Gets the type that implements the state machine.
+ public Type StateMachineType { get; private set; }
+ }
+}
diff --git a/Microsoft.Bcl/System.Runtime.v1.5/System/Tuple.cs b/Microsoft.Bcl/System.Runtime.v1.5/System/Tuple.cs
new file mode 100644
index 000000000..78243bd82
--- /dev/null
+++ b/Microsoft.Bcl/System.Runtime.v1.5/System/Tuple.cs
@@ -0,0 +1,1677 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//--------------------------------------------------------------------------
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace System
+{
+ ///
+ /// Helper so we can call some tuple methods recursively without knowing the underlying types.
+ ///
+ internal interface ITuple
+ {
+ string ToString(StringBuilder sb);
+ int GetHashCode(IEqualityComparer comparer);
+ int Size { get; }
+ }
+
+ ///
+ /// Provides static methods for creating tuple objects.
+ ///
+ public static class Tuple
+ {
+ ///
+ /// Creates a new 1-tuple, or singleton.
+ ///
+ /// The type of the only component of the tuple.
+ /// The value of the only component of the tuple.
+ /// A tuple whose value is (item1).
+ public static Tuple Create(T1 item1)
+ {
+ return new Tuple(item1);
+ }
+
+ ///
+ /// Creates a new 3-tuple, or pair.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// An 2-tuple (pair) whose value is (item1, item2).
+ public static Tuple Create(T1 item1, T2 item2)
+ {
+ return new Tuple(item1, item2);
+ }
+
+ ///
+ /// Creates a new 3-tuple, or triple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// An 3-tuple (triple) whose value is (item1, item2, item3).
+ public static Tuple Create(T1 item1, T2 item2, T3 item3)
+ {
+ return new Tuple(item1, item2, item3);
+ }
+
+ ///
+ /// Creates a new 4-tuple, or quadruple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// An 4-tuple (quadruple) whose value is (item1, item2, item3, item4).
+ public static Tuple Create(T1 item1, T2 item2, T3 item3, T4 item4)
+ {
+ return new Tuple(item1, item2, item3, item4);
+ }
+
+ ///
+ /// Creates a new 5-tuple, or quintuple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// An 5-tuple (quintuple) whose value is (item1, item2, item3, item4, item5).
+ public static Tuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
+ {
+ return new Tuple(item1, item2, item3, item4, item5);
+ }
+
+ ///
+ /// Creates a new 6-tuple, or sextuple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The type of the sixth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// The value of the sixth component of the tuple.
+ /// An 6-tuple (sextuple) whose value is (item1, item2, item3, item4, item5, item6).
+ public static Tuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
+ {
+ return new Tuple(item1, item2, item3, item4, item5, item6);
+ }
+
+ ///
+ /// Creates a new 7-tuple, or septuple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The type of the sixth component of the tuple.
+ /// The type of the seventh component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// The value of the sixth component of the tuple.
+ /// The value of the seventh component of the tuple.
+ /// An 7-tuple (septuple) whose value is (item1, item2, item3, item4, item5, item6, item7).
+ public static Tuple Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
+ {
+ return new Tuple(item1, item2, item3, item4, item5, item6, item7);
+ }
+
+ ///
+ /// Creates a new 8-tuple, or octuple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ /// The type of the fifth component of the tuple.
+ /// The type of the sixth component of the tuple.
+ /// The type of the seventh component of the tuple.
+ /// The type of the eighth component of the tuple.
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ /// The value of the fourth component of the tuple.
+ /// The value of the fifth component of the tuple.
+ /// The value of the sixth component of the tuple.
+ /// The value of the seventh component of the tuple.
+ /// The value of the eighth component of the tuple.
+ /// An 8-tuple (octuple) whose value is (item1, item2, item3, item4, item5, item6, item7, item8).
+ public static Tuple> Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
+ {
+ return new Tuple>(item1, item2, item3, item4, item5, item6, item7, new Tuple(item8));
+ }
+
+ // From System.Web.Util.HashCodeCombiner
+ internal static int CombineHashCodes(int h1, int h2)
+ {
+ return (((h1 << 5) + h1) ^ h2);
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2), h3);
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2), CombineHashCodes(h3, h4));
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6));
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7));
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)
+ {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7, h8));
+ }
+ }
+
+ ///
+ /// Represents a 1-tuple, or singleton.
+ ///
+ /// The type of the tuple's only component.
+ public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
+ {
+ private readonly T1 m_Item1;
+
+ ///
+ /// Gets the value of the tuple object's single component.
+ ///
+ ///
+ /// The value of the current tuple object's single component.
+ ///
+ public T1 Item1 { get { return m_Item1; } }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of the current tuple object's single component.
+ public Tuple(T1 item1)
+ {
+ m_Item1 = item1;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current tuple object is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// true if the current instance is equal to the specified object; otherwise, false.
+ public override Boolean Equals(Object obj)
+ {
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default);
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ {
+ if (other == null) return false;
+
+ Tuple objTuple = other as Tuple;
+
+ if (objTuple == null)
+ {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1);
+ }
+
+ Int32 IComparable.CompareTo(Object obj)
+ {
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ {
+ if (other == null) return 1;
+
+ Tuple objTuple = other as Tuple;
+
+ if (objTuple == null)
+ {
+ throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, Strings.ArgumentException_TupleIncorrectType, GetType().ToString()), "other");
+ }
+
+ return comparer.Compare(m_Item1, objTuple.m_Item1);
+ }
+
+ ///
+ /// Calculates the hash code for the current tuple object.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ {
+ return comparer.GetHashCode(m_Item1);
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer)
+ {
+ return ((IStructuralEquatable)this).GetHashCode(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this tuple instance.
+ ///
+ /// The string representation of this tuple object.
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb)
+ {
+ sb.Append(m_Item1);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size
+ {
+ get
+ {
+ return 1;
+ }
+ }
+ }
+
+ ///
+ /// Represents an 2-tuple, or pair.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
+ {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+
+ ///
+ /// Gets the value of the current tuple object's first component.
+ ///
+ ///
+ /// The value of the current tuple object's first component.
+ ///
+ public T1 Item1 { get { return m_Item1; } }
+
+ ///
+ /// Gets the value of the current tuple object's second component.
+ ///
+ ///
+ /// The value of the current tuple object's second component.
+ ///
+ public T2 Item2 { get { return m_Item2; } }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ public Tuple(T1 item1, T2 item2)
+ {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current tuple object is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// true if the current instance is equal to the specified object; otherwise, false.
+ public override Boolean Equals(Object obj)
+ {
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ {
+ if (other == null) return false;
+
+ Tuple objTuple = other as Tuple;
+
+ if (objTuple == null)
+ {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2);
+ }
+
+ Int32 IComparable.CompareTo(Object obj)
+ {
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ {
+ if (other == null) return 1;
+
+ Tuple objTuple = other as Tuple;
+
+ if (objTuple == null)
+ {
+ throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, Strings.ArgumentException_TupleIncorrectType, GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item2, objTuple.m_Item2);
+ }
+
+ ///
+ /// Calculates the hash code for the current tuple object.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer)
+ {
+ return ((IStructuralEquatable)this).GetHashCode(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this tuple instance.
+ ///
+ /// The string representation of this tuple object.
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb)
+ {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+
+ ///
+ /// Represents an 3-tuple, or triple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
+ {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+
+ ///
+ /// Gets the value of the current tuple object's first component.
+ ///
+ ///
+ /// The value of the current tuple object's first component.
+ ///
+ public T1 Item1 { get { return m_Item1; } }
+
+ ///
+ /// Gets the value of the current tuple object's second component.
+ ///
+ ///
+ /// The value of the current tuple object's second component.
+ ///
+ public T2 Item2 { get { return m_Item2; } }
+
+ ///
+ /// Gets the value of the current tuple object's third component.
+ ///
+ ///
+ /// The value of the current tuple object's third component.
+ ///
+ public T3 Item3 { get { return m_Item3; } }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of the first component of the tuple.
+ /// The value of the second component of the tuple.
+ /// The value of the third component of the tuple.
+ public Tuple(T1 item1, T2 item2, T3 item3)
+ {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ }
+
+ ///
+ /// Returns a value that indicates whether the current tuple object is equal to a specified object.
+ ///
+ /// The object to compare with this instance.
+ /// true if the current instance is equal to the specified object; otherwise, false.
+ public override Boolean Equals(Object obj)
+ {
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer.Default); ;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ {
+ if (other == null) return false;
+
+ Tuple objTuple = other as Tuple;
+
+ if (objTuple == null)
+ {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3);
+ }
+
+ Int32 IComparable.CompareTo(Object obj)
+ {
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ {
+ if (other == null) return 1;
+
+ Tuple objTuple = other as Tuple;
+
+ if (objTuple == null)
+ {
+ throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, Strings.ArgumentException_TupleIncorrectType, GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item3, objTuple.m_Item3);
+ }
+
+ ///
+ /// Calculates the hash code for the current tuple object.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer)
+ {
+ return ((IStructuralEquatable)this).GetHashCode(comparer);
+ }
+
+ ///
+ /// Returns a string that represents the value of this tuple instance.
+ ///
+ /// The string representation of this tuple object.
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb)
+ {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size
+ {
+ get
+ {
+ return 3;
+ }
+ }
+ }
+
+ ///
+ /// Represents an 4-tuple, or quadruple.
+ ///
+ /// The type of the first component of the tuple.
+ /// The type of the second component of the tuple.
+ /// The type of the third component of the tuple.
+ /// The type of the fourth component of the tuple.
+ public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
+ {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+ private readonly T4 m_Item4;
+
+ ///