diff --git a/Lib/AspNet/Microsoft.WindowsAzure.Storage/Extensions/StreamExtension.cs b/Lib/AspNet/Microsoft.WindowsAzure.Storage/Extensions/StreamExtension.cs index 0bdf81102..f28c73792 100644 --- a/Lib/AspNet/Microsoft.WindowsAzure.Storage/Extensions/StreamExtension.cs +++ b/Lib/AspNet/Microsoft.WindowsAzure.Storage/Extensions/StreamExtension.cs @@ -71,9 +71,9 @@ public static Stream AsStreamForWrite(this Stream stream) /// input stream /// buffer to write to the stream /// Async task - public static async Task WriteAsync(this Stream stream, byte[] buffer) + public static Task WriteAsync(this Stream stream, byte[] buffer) { - await stream.WriteAsync(buffer, 0, buffer.Length); + return stream.WriteAsync(buffer, 0, buffer.Length); } /// diff --git a/Lib/ClassLibraryCommon/Table/Protocol/HttpResponseAdapterMessage.cs b/Lib/ClassLibraryCommon/Table/Protocol/HttpResponseAdapterMessage.cs index 41c7a6064..a7a20cd1e 100644 --- a/Lib/ClassLibraryCommon/Table/Protocol/HttpResponseAdapterMessage.cs +++ b/Lib/ClassLibraryCommon/Table/Protocol/HttpResponseAdapterMessage.cs @@ -27,7 +27,7 @@ namespace Microsoft.WindowsAzure.Storage.Table.Protocol internal class HttpResponseAdapterMessage : IODataResponseMessage { private HttpWebResponse resp = null; - private Stream str = null; + private Task strAsCachedTask = null; private string responseContentType = null; public HttpResponseAdapterMessage(HttpWebResponse resp, Stream str) @@ -38,13 +38,13 @@ public HttpResponseAdapterMessage(HttpWebResponse resp, Stream str) public HttpResponseAdapterMessage(HttpWebResponse resp, Stream str, string responseContentType) { this.resp = resp; - this.str = str; + this.strAsCachedTask = Task.FromResult(str); this.responseContentType = responseContentType; } public Task GetStreamAsync() { - return Task.Factory.StartNew(() => this.str); + return this.strAsCachedTask; } public string GetHeader(string headerName) @@ -73,7 +73,7 @@ public string GetHeader(string headerName) public Stream GetStream() { - return this.str; + return this.strAsCachedTask.Result; // safe since completed task and avoids additional field for stream } public IEnumerable> Headers diff --git a/Lib/Common/Core/MultiBufferMemoryStream.cs b/Lib/Common/Core/MultiBufferMemoryStream.cs index 8b05821c0..ccb2d6ea4 100644 --- a/Lib/Common/Core/MultiBufferMemoryStream.cs +++ b/Lib/Common/Core/MultiBufferMemoryStream.cs @@ -572,7 +572,7 @@ public async Task FastCopyToAsync(Stream destination, DateTime? expiryTime) // Copy the block int blockReadLength = (int)Math.Min(leftToRead, currentBlock.Count); - await destination.WriteAsync(currentBlock.Array, currentBlock.Offset, blockReadLength); + await destination.WriteAsync(currentBlock.Array, currentBlock.Offset, blockReadLength).ConfigureAwait(false); this.AdvancePosition(ref leftToRead, blockReadLength); } diff --git a/Lib/Common/Core/NullType.cs b/Lib/Common/Core/NullType.cs index 02162009b..3c22f2724 100644 --- a/Lib/Common/Core/NullType.cs +++ b/Lib/Common/Core/NullType.cs @@ -15,6 +15,8 @@ // //----------------------------------------------------------------------- +using System.Threading.Tasks; + namespace Microsoft.WindowsAzure.Storage.Core { /// @@ -27,6 +29,11 @@ public sealed class NullType /// internal static readonly NullType Value = new NullType(); + /// + /// Represents a no-return from a task. + /// + internal static readonly Task ValueTask = Task.FromResult(Value); + /// /// Prevents a default instance of the class from being created. /// diff --git a/Lib/Common/Core/Util/Exceptions.cs b/Lib/Common/Core/Util/Exceptions.cs index 9b106e7db..a8f094aee 100644 --- a/Lib/Common/Core/Util/Exceptions.cs +++ b/Lib/Common/Core/Util/Exceptions.cs @@ -68,7 +68,7 @@ internal async static Task PopulateStorageExceptionFromHttpRes } else { - currentResult.ExtendedErrorInformation = await StorageExtendedErrorInformation.ReadFromStreamAsync(errStream.AsInputStream()); + currentResult.ExtendedErrorInformation = await StorageExtendedErrorInformation.ReadFromStreamAsync(errStream.AsInputStream()).ConfigureAwait(false); } } catch (Exception) diff --git a/Lib/Common/StorageExtendedErrorInformation.cs b/Lib/Common/StorageExtendedErrorInformation.cs index f6becff77..870f9a160 100644 --- a/Lib/Common/StorageExtendedErrorInformation.cs +++ b/Lib/Common/StorageExtendedErrorInformation.cs @@ -77,9 +77,9 @@ public static StorageExtendedErrorInformation ReadFromStream(IInputStream inputS return ReadFromStream(inputStream.AsStreamForRead()); } - public static async Task ReadFromStreamAsync(IInputStream inputStream) + public static Task ReadFromStreamAsync(IInputStream inputStream) { - return await ReadFromStreamAsync(inputStream.AsStreamForRead()); + return ReadFromStreamAsync(inputStream.AsStreamForRead()); } #endif @@ -139,7 +139,7 @@ public static async Task ReadFromStreamAsync(St using (XmlReader reader = XmlReader.Create(inputStream, settings)) { - await reader.ReadAsync(); + await reader.ReadAsync().ConfigureAwait(false); extendedErrorInfo.ReadXml(reader); } diff --git a/Lib/WindowsDesktop/Table/DataServices/DataServicesResponseAdapterMessage.cs b/Lib/WindowsDesktop/Table/DataServices/DataServicesResponseAdapterMessage.cs index 85dcd612f..c59c09d75 100644 --- a/Lib/WindowsDesktop/Table/DataServices/DataServicesResponseAdapterMessage.cs +++ b/Lib/WindowsDesktop/Table/DataServices/DataServicesResponseAdapterMessage.cs @@ -26,7 +26,7 @@ namespace Microsoft.WindowsAzure.Storage.Table.DataServices internal class DataServicesResponseAdapterMessage : IODataResponseMessage { private IDictionary responseHeaders; - private Stream inputStream = null; + private Task inputStreamAsCachedTask = null; private string responseContentType = null; public DataServicesResponseAdapterMessage(Dictionary responseHeaders, Stream inputStream) @@ -37,13 +37,13 @@ public DataServicesResponseAdapterMessage(Dictionary responseHea public DataServicesResponseAdapterMessage(IDictionary responseHeaders, Stream inputStream, string responseContentType) { this.responseHeaders = responseHeaders; - this.inputStream = inputStream; + this.inputStreamAsCachedTask = Task.FromResult(inputStream); this.responseContentType = responseContentType; } public Task GetStreamAsync() { - return Task.Factory.StartNew(() => this.inputStream); + return inputStreamAsCachedTask; } public string GetHeader(string headerName) @@ -77,7 +77,7 @@ public string GetHeader(string headerName) public Stream GetStream() { - return this.inputStream; + return this.inputStreamAsCachedTask.Result; // safe since completed task and avoids additional field for stream } public IEnumerable> Headers diff --git a/Lib/WindowsRuntime/Blob/BlobReadStream.cs b/Lib/WindowsRuntime/Blob/BlobReadStream.cs index ea0f005a5..1b2d0c20e 100644 --- a/Lib/WindowsRuntime/Blob/BlobReadStream.cs +++ b/Lib/WindowsRuntime/Blob/BlobReadStream.cs @@ -95,7 +95,7 @@ public override int Read(byte[] buffer, int offset, int count) /// The maximum number of bytes to read. /// The token to monitor for cancellation requests. /// A task that represents the asynchronous read operation. - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("buffer", buffer); CommonUtility.AssertInBounds("offset", offset, 0, buffer.Length); @@ -108,16 +108,16 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, if ((this.currentOffset == this.Length) || (count == 0)) { - return 0; + return Task.FromResult(0); } int readCount = this.ConsumeBuffer(buffer, offset, count); if (readCount > 0) { - return readCount; + return Task.FromResult(readCount); } - return await this.DispatchReadAsync(buffer, offset, count); + return this.DispatchReadAsync(buffer, offset, count); } /// @@ -140,7 +140,7 @@ await this.blob.DownloadRangeToStreamAsync( this.GetReadSize(), this.accessCondition, this.options, - this.operationContext); + this.operationContext).ConfigureAwait(false); this.internalBuffer.Seek(0, SeekOrigin.Begin); return this.ConsumeBuffer(buffer, offset, count); diff --git a/Lib/WindowsRuntime/Blob/BlobWriteStream.cs b/Lib/WindowsRuntime/Blob/BlobWriteStream.cs index 17ece7ef3..281cdd28a 100644 --- a/Lib/WindowsRuntime/Blob/BlobWriteStream.cs +++ b/Lib/WindowsRuntime/Blob/BlobWriteStream.cs @@ -158,7 +158,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc if (bytesToWrite == maxBytesToWrite) { - await this.DispatchWriteAsync(); + await this.DispatchWriteAsync().ConfigureAwait(false); } } } @@ -188,7 +188,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken) throw new InvalidOperationException(SR.BlobStreamAlreadyCommitted); } - await this.DispatchWriteAsync(); + await this.DispatchWriteAsync().ConfigureAwait(false); await Task.Run(() => this.noPendingWritesEvent.Wait(), cancellationToken); if (this.lastException != null) @@ -225,7 +225,7 @@ protected override void Dispose(bool disposing) /// A task that represents the asynchronous commit operation. public override async Task CommitAsync() { - await this.FlushAsync(); + await this.FlushAsync().ConfigureAwait(false); this.committed = true; try @@ -237,14 +237,14 @@ public override async Task CommitAsync() this.blockBlob.Properties.ContentMD5 = this.blobMD5.ComputeHash(); } - await this.blockBlob.PutBlockListAsync(this.blockList, this.accessCondition, this.options, this.operationContext); + await this.blockBlob.PutBlockListAsync(this.blockList, this.accessCondition, this.options, this.operationContext).ConfigureAwait(false); } else { if (this.blobMD5 != null) { this.Blob.Properties.ContentMD5 = this.blobMD5.ComputeHash(); - await this.Blob.SetPropertiesAsync(this.accessCondition, this.options, this.operationContext); + await this.Blob.SetPropertiesAsync(this.accessCondition, this.options, this.operationContext).ConfigureAwait(false); } } } @@ -282,7 +282,7 @@ private async Task DispatchWriteAsync() { string blockId = this.GetCurrentBlockId(); this.blockList.Add(blockId); - await this.WriteBlockAsync(bufferToUpload, blockId, bufferMD5); + await this.WriteBlockAsync(bufferToUpload, blockId, bufferMD5).ConfigureAwait(false); } else if (this.pageBlob != null) { @@ -294,7 +294,7 @@ private async Task DispatchWriteAsync() long offset = this.currentBlobOffset; this.currentBlobOffset += bufferToUpload.Length; - await this.WritePagesAsync(bufferToUpload, offset, bufferMD5); + await this.WritePagesAsync(bufferToUpload, offset, bufferMD5).ConfigureAwait(false); } else { @@ -310,7 +310,7 @@ private async Task DispatchWriteAsync() throw this.lastException; } - await this.WriteAppendBlockAsync(bufferToUpload, offset, bufferMD5); + await this.WriteAppendBlockAsync(bufferToUpload, offset, bufferMD5).ConfigureAwait(false); } } @@ -324,7 +324,7 @@ private async Task DispatchWriteAsync() private async Task WriteBlockAsync(Stream blockData, string blockId, string blockMD5) { this.noPendingWritesEvent.Increment(); - await this.parallelOperationSemaphore.WaitAsync(); + await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false); Task putBlockTask = this.blockBlob.PutBlockAsync(blockId, blockData, blockMD5, this.accessCondition, this.options, this.operationContext).ContinueWith(task => { if (task.Exception != null) @@ -347,7 +347,7 @@ private async Task WriteBlockAsync(Stream blockData, string blockId, string bloc private async Task WritePagesAsync(Stream pageData, long offset, string contentMD5) { this.noPendingWritesEvent.Increment(); - await this.parallelOperationSemaphore.WaitAsync(); + await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false); Task writePagesTask = this.pageBlob.WritePagesAsync(pageData, offset, contentMD5, this.accessCondition, this.options, this.operationContext).ContinueWith(task => { if (task.Exception != null) @@ -372,7 +372,7 @@ private async Task WritePagesAsync(Stream pageData, long offset, string contentM private async Task WriteAppendBlockAsync(Stream blockData, long offset, string blockMD5) { this.noPendingWritesEvent.Increment(); - await this.parallelOperationSemaphore.WaitAsync(); + await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false); this.accessCondition.IfAppendPositionEqual = offset; diff --git a/Lib/WindowsRuntime/Blob/CloudAppendBlob.cs b/Lib/WindowsRuntime/Blob/CloudAppendBlob.cs index 8a157fadc..0fe717892 100644 --- a/Lib/WindowsRuntime/Blob/CloudAppendBlob.cs +++ b/Lib/WindowsRuntime/Blob/CloudAppendBlob.cs @@ -80,7 +80,7 @@ public virtual Task OpenWriteAsync(bool createNew, AccessCondit /// A to observe while waiting for a task to complete. /// A stream to be used for writing to the blob. [DoesServiceRequest] - public virtual Task OpenWriteAsync(bool createNew, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task OpenWriteAsync(bool createNew, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { this.attributes.AssertNoSnapshot(); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.AppendBlob, this.ServiceClient, false); @@ -89,27 +89,24 @@ public virtual Task OpenWriteAsync(bool createNew, AccessCondit throw new ArgumentException(SR.MD5NotPossible); } - return Task.Run(async () => + if (createNew) { - if (createNew) - { - await this.CreateOrReplaceAsync(accessCondition, options, operationContext, cancellationToken); - } - else - { - // Although we don't need any properties from the service, we should make this call in order to honor the user specified conditional headers - // while opening an existing stream and to get the append position for an existing blob if user didn't specify one. - await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken); - } + await this.CreateOrReplaceAsync(accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } + else + { + // Although we don't need any properties from the service, we should make this call in order to honor the user specified conditional headers + // while opening an existing stream and to get the append position for an existing blob if user didn't specify one. + await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } - if (accessCondition != null) - { - accessCondition = new AccessCondition() { LeaseId = accessCondition.LeaseId, IfAppendPositionEqual = accessCondition.IfAppendPositionEqual, IfMaxSizeLessThanOrEqual = accessCondition.IfMaxSizeLessThanOrEqual }; - } + if (accessCondition != null) + { + accessCondition = new AccessCondition() { LeaseId = accessCondition.LeaseId, IfAppendPositionEqual = accessCondition.IfAppendPositionEqual, IfMaxSizeLessThanOrEqual = accessCondition.IfMaxSizeLessThanOrEqual }; + } - CloudBlobStream stream = new BlobWriteStream(this, accessCondition, modifiedOptions, operationContext); - return stream; - }, cancellationToken); + CloudBlobStream stream = new BlobWriteStream(this, accessCondition, modifiedOptions, operationContext); + return stream; } /// @@ -358,7 +355,7 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, bool crea /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - internal Task UploadFromStreamAsyncHelper(Stream source, long? length, bool createNew, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + internal async Task UploadFromStreamAsyncHelper(Stream source, long? length, bool createNew, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("source", source); @@ -377,16 +374,13 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, bool crea operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => + using (CloudBlobStream blobStream = await this.OpenWriteAsync(createNew, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false)) { - using (CloudBlobStream blobStream = await this.OpenWriteAsync(createNew, accessCondition, options, operationContext, cancellationToken)) - { - // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our - // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. - await source.WriteToAsync(blobStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken); - await blobStream.CommitAsync(); - } - }, cancellationToken); + // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our + // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. + await source.WriteToAsync(blobStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken).ConfigureAwait(false); + await blobStream.CommitAsync().ConfigureAwait(false); + } } /// @@ -472,17 +466,14 @@ public virtual Task UploadFromFileAsync(StorageFile source, AccessCondition acce /// To append data to an append blob that already exists, see . /// [DoesServiceRequest] - public virtual Task UploadFromFileAsync(string path, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task UploadFromFileAsync(string path, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("path", path); - return Task.Run(async () => + using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { - using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - await this.UploadFromStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - } - }, cancellationToken); + await this.UploadFromStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #else /// The file providing the blob content. @@ -502,13 +493,10 @@ public virtual Task UploadFromFileAsync(StorageFile source, AccessCondition acce { CommonUtility.AssertNotNull("source", source); - return Task.Run(async () => + using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken).ConfigureAwait(false)) { - using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken)) - { - await this.UploadFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken); - } - }); + await this.UploadFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -581,17 +569,14 @@ public virtual Task AppendFromFileAsync(StorageFile source, AccessCondition acce /// If you have a single-writer scenario, see to determine whether setting this flag to true is acceptable for your scenario. /// [DoesServiceRequest] - public virtual Task AppendFromFileAsync(string path, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task AppendFromFileAsync(string path, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("path", path); - return Task.Run(async () => + using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { - using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - await this.AppendFromStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - } - }, cancellationToken); + await this.AppendFromStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #else /// The file providing the blob content. @@ -609,13 +594,10 @@ public virtual Task AppendFromFileAsync(StorageFile source, AccessCondition acce CommonUtility.AssertNotNull("source", source); - return Task.Run(async () => + using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken).ConfigureAwait(false)) { - using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken)) - { - await this.AppendFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken); - } - }); + await this.AppendFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -889,11 +871,11 @@ public virtual Task CreateOrReplaceAsync(AccessCondition accessCondition, BlobRe public virtual Task CreateOrReplaceAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.AppendBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -947,60 +929,57 @@ public virtual Task AppendBlockAsync(Stream blockData, string contentMD5, /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task AppendBlockAsync(Stream blockData, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task AppendBlockAsync(Stream blockData, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.AppendBlob, this.ServiceClient); bool requiresContentMD5 = string.IsNullOrEmpty(contentMD5) && modifiedOptions.UseTransactionalMD5.Value; operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => - { - Stream blockDataAsStream = blockData; - Stream seekableStream = blockDataAsStream; - bool seekableStreamCreated = false; + Stream blockDataAsStream = blockData; + Stream seekableStream = blockDataAsStream; + bool seekableStreamCreated = false; - try + try + { + if (!blockDataAsStream.CanSeek || requiresContentMD5) { - if (!blockDataAsStream.CanSeek || requiresContentMD5) + Stream writeToStream; + if (blockDataAsStream.CanSeek) + { + writeToStream = Stream.Null; + } + else { - Stream writeToStream; - if (blockDataAsStream.CanSeek) - { - writeToStream = Stream.Null; - } - else - { - seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); - seekableStreamCreated = true; - writeToStream = seekableStream; - } - - StreamDescriptor streamCopyState = new StreamDescriptor(); - long startPosition = seekableStream.Position; - await blockDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxAppendBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken); - seekableStream.Position = startPosition; - - if (requiresContentMD5) - { - contentMD5 = streamCopyState.Md5; - } + seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); + seekableStreamCreated = true; + writeToStream = seekableStream; } - return await Executor.ExecuteAsync( - this.AppendBlockImpl(seekableStream, contentMD5, accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - } - finally - { - if (seekableStreamCreated) + StreamDescriptor streamCopyState = new StreamDescriptor(); + long startPosition = seekableStream.Position; + await blockDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxAppendBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken).ConfigureAwait(false); + seekableStream.Position = startPosition; + + if (requiresContentMD5) { - seekableStream.Dispose(); + contentMD5 = streamCopyState.Md5; } } - }, cancellationToken); + + return await Executor.ExecuteAsync( + this.AppendBlockImpl(seekableStream, contentMD5, accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + } + finally + { + if (seekableStreamCreated) + { + seekableStream.Dispose(); + } + } } /// @@ -1037,17 +1016,14 @@ public virtual Task DownloadTextAsync(Encoding encoding, AccessCondition /// A to observe while waiting for a task to complete. /// The contents of the blob, as a string. [DoesServiceRequest] - public virtual Task DownloadTextAsync(Encoding encoding, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadTextAsync(Encoding encoding, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => + using (SyncMemoryStream stream = new SyncMemoryStream()) { - using (SyncMemoryStream stream = new SyncMemoryStream()) - { - await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - byte[] streamAsBytes = stream.ToArray(); - return (encoding ?? Encoding.UTF8).GetString(streamAsBytes, 0, streamAsBytes.Length); - } - }, cancellationToken); + await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + byte[] streamAsBytes = stream.ToArray(); + return (encoding ?? Encoding.UTF8).GetString(streamAsBytes, 0, streamAsBytes.Length); + } } /// @@ -1142,11 +1118,11 @@ public virtual Task CreateSnapshotAsync(IDictionary await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.CreateSnapshotImpl(metadata, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// diff --git a/Lib/WindowsRuntime/Blob/CloudBlob.cs b/Lib/WindowsRuntime/Blob/CloudBlob.cs index 48527f2ce..d9e6ca9b1 100644 --- a/Lib/WindowsRuntime/Blob/CloudBlob.cs +++ b/Lib/WindowsRuntime/Blob/CloudBlob.cs @@ -76,15 +76,12 @@ public virtual Task OpenReadAsync(AccessCondition accessCondition, BlobR /// A to observe while waiting for a task to complete. /// A stream to be used for reading from the blob. [DoesServiceRequest] - public virtual Task OpenReadAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task OpenReadAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => - { - await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken); - AccessCondition streamAccessCondition = AccessCondition.CloneConditionWithETag(accessCondition, this.Properties.ETag); - BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, this.BlobType, this.ServiceClient, false); - return new BlobReadStream(this, streamAccessCondition, modifiedOptions, operationContext); - }, cancellationToken); + await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + AccessCondition streamAccessCondition = AccessCondition.CloneConditionWithETag(accessCondition, this.Properties.ETag); + BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, this.BlobType, this.ServiceClient, false); + return new BlobReadStream(this, streamAccessCondition, modifiedOptions, operationContext); } /// @@ -188,14 +185,11 @@ public virtual Task DownloadToFileAsync(StorageFile target, AccessCondition acce [DoesServiceRequest] public virtual Task DownloadToFileAsync(StorageFile target, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => + using (StorageStreamTransaction transaction = await target.OpenTransactedWriteAsync().AsTask(cancellationToken)) { - using (StorageStreamTransaction transaction = await target.OpenTransactedWriteAsync().AsTask(cancellationToken)) - { - await this.DownloadToStreamAsync(transaction.Stream.AsStream(), accessCondition, options, operationContext, cancellationToken); - await transaction.CommitAsync(); - } - }); + await this.DownloadToStreamAsync(transaction.Stream.AsStream(), accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + await transaction.CommitAsync().ConfigureAwait(false); + } } #endif @@ -211,40 +205,36 @@ public virtual Task DownloadToFileAsync(StorageFile target, AccessCondition acce /// A to observe while waiting for a task to complete. /// An that represents an asynchronous action. [DoesServiceRequest] - public virtual Task DownloadToFileAsync(string path, FileMode mode, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadToFileAsync(string path, FileMode mode, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("path", path); - return Task.Run(async () => - { - FileStream stream = new FileStream(path, mode, FileAccess.Write); + FileStream stream = new FileStream(path, mode, FileAccess.Write); - try + try + { + using (stream) { - using (stream) - { - await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - } + await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); } - catch (Exception) + } + catch (Exception) + { + if (mode == FileMode.Create || mode == FileMode.CreateNew) { - if (mode == FileMode.Create || mode == FileMode.CreateNew) + try { - try - { - File.Delete(path); - } - catch (Exception) - { - // Best effort to clean up in the event that download was unsuccessful. - // Do not throw as we want to throw original exception. - } + File.Delete(path); + } + catch (Exception) + { + // Best effort to clean up in the event that download was unsuccessful. + // Do not throw as we want to throw original exception. } - - throw; } - }, cancellationToken); + throw; + } } #endif @@ -340,11 +330,11 @@ public virtual Task DownloadRangeToStreamAsync(Stream target, long? offset, long // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.GetBlobImpl(this.attributes, target, offset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -391,16 +381,13 @@ public virtual Task DownloadRangeToByteArrayAsync(byte[] target, int index, /// A to observe while waiting for a task to complete. /// The total number of bytes read into the buffer. [DoesServiceRequest] - public virtual Task DownloadRangeToByteArrayAsync(byte[] target, int index, long? blobOffset, long? length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadRangeToByteArrayAsync(byte[] target, int index, long? blobOffset, long? length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => + using (SyncMemoryStream stream = new SyncMemoryStream(target, index)) { - using (SyncMemoryStream stream = new SyncMemoryStream(target, index)) - { - await this.DownloadRangeToStreamAsync(stream, blobOffset, length, accessCondition, options, operationContext, cancellationToken); - return (int)stream.Position; - } - }, cancellationToken); + await this.DownloadRangeToStreamAsync(stream, blobOffset, length, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + return (int)stream.Position; + } } /// @@ -449,11 +436,11 @@ public virtual Task ExistsAsync(BlobRequestOptions options, OperationConte private Task ExistsAsync(bool primaryOnly, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ExistsImpl(this.attributes, modifiedOptions, primaryOnly), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -491,11 +478,11 @@ public virtual Task FetchAttributesAsync(AccessCondition accessCondition, BlobRe public virtual Task FetchAttributesAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.FetchAttributesImpl(this.attributes, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -534,11 +521,11 @@ public virtual Task SetMetadataAsync(AccessCondition accessCondition, BlobReques { this.attributes.AssertNoSnapshot(); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetMetadataImpl(this.attributes, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -577,11 +564,11 @@ public virtual Task SetPropertiesAsync(AccessCondition accessCondition, BlobRequ { this.attributes.AssertNoSnapshot(); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetPropertiesImpl(this.attributes, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -621,11 +608,11 @@ public virtual Task DeleteAsync(DeleteSnapshotsOption deleteSnapshotsOption, Acc public virtual Task DeleteAsync(DeleteSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteBlobImpl(this.attributes, deleteSnapshotsOption, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -662,40 +649,37 @@ public virtual Task DeleteIfExistsAsync(DeleteSnapshotsOption deleteSnapsh /// A to observe while waiting for a task to complete. /// true if the blob already existed and was deleted; otherwise, false. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(DeleteSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(DeleteSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, this.BlobType, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try - { - await this.DeleteAsync(deleteSnapshotsOption, accessCondition, modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + await this.DeleteAsync(deleteSnapshotsOption, accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == BlobErrorCodeStrings.BlobNotFound) || + (extendedInfo.ErrorCode == BlobErrorCodeStrings.ContainerNotFound)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == BlobErrorCodeStrings.BlobNotFound) || - (extendedInfo.ErrorCode == BlobErrorCodeStrings.ContainerNotFound)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }); + else + { + throw; + } + } } /// @@ -745,11 +729,11 @@ public virtual Task AcquireLeaseAsync(TimeSpan? leaseTime, string propos public virtual Task AcquireLeaseAsync(TimeSpan? leaseTime, string proposedLeaseId, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.AcquireLeaseImpl(this.attributes, leaseTime, proposedLeaseId, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -788,11 +772,11 @@ public virtual Task RenewLeaseAsync(AccessCondition accessCondition, BlobRequest public virtual Task RenewLeaseAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.RenewLeaseImpl(this.attributes, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -834,11 +818,11 @@ public virtual Task ChangeLeaseAsync(string proposedLeaseId, AccessCondi public virtual Task ChangeLeaseAsync(string proposedLeaseId, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ChangeLeaseImpl(this.attributes, proposedLeaseId, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -877,11 +861,11 @@ public virtual Task ReleaseLeaseAsync(AccessCondition accessCondition, BlobReque public virtual Task ReleaseLeaseAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ReleaseLeaseImpl(this.attributes, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -928,11 +912,11 @@ public virtual Task BreakLeaseAsync(TimeSpan? breakPeriod, AccessCondi public virtual Task BreakLeaseAsync(TimeSpan? breakPeriod, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.BreakLeaseImpl(this.attributes, breakPeriod, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -973,11 +957,11 @@ public virtual Task SnapshotAsync(IDictionary metadat { this.attributes.AssertNoSnapshot(); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.SnapshotImpl(metadata, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1050,11 +1034,11 @@ internal virtual Task StartCopyAsync(Uri source, PremiumPageBlobTier? pr { CommonUtility.AssertNotNull("source", source); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.StartCopyImpl(this.attributes, source, false /* incrementalCopy */, premiumPageBlobTier, sourceAccessCondition, destAccessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1096,11 +1080,11 @@ public virtual Task AbortCopyAsync(string copyId, AccessCondition accessConditio public virtual Task AbortCopyAsync(string copyId, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.AppendBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.AbortCopyImpl(this.attributes, copyId, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1198,7 +1182,7 @@ private RESTCommand GetBlobImpl(BlobAttributes attributes, Stream dest getCmd.PostProcessResponse = (cmd, resp, ctx) => { HttpResponseParsers.ValidateResponseStreamMd5AndLength(validateLength, storedMD5, cmd); - return Task.FromResult(NullType.Value); + return NullType.ValueTask; }; return getCmd; diff --git a/Lib/WindowsRuntime/Blob/CloudBlobClient.cs b/Lib/WindowsRuntime/Blob/CloudBlobClient.cs index a5a8237e0..7b1eac127 100644 --- a/Lib/WindowsRuntime/Blob/CloudBlobClient.cs +++ b/Lib/WindowsRuntime/Blob/CloudBlobClient.cs @@ -111,19 +111,16 @@ public virtual Task ListContainersSegmentedAsync(string /// A to observe while waiting for a task to complete. /// A result segment of containers. [DoesServiceRequest] - public virtual Task ListContainersSegmentedAsync(string prefix, ContainerListingDetails detailsIncluded, int? maxResults, BlobContinuationToken currentToken, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task ListContainersSegmentedAsync(string prefix, ContainerListingDetails detailsIncluded, int? maxResults, BlobContinuationToken currentToken, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => - { - BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this); - ResultSegment resultSegment = await Executor.ExecuteAsync( - this.ListContainersImpl(prefix, detailsIncluded, currentToken, maxResults, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - - return new ContainerResultSegment(resultSegment.Results, (BlobContinuationToken)resultSegment.ContinuationToken); - }, cancellationToken); + BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this); + ResultSegment resultSegment = await Executor.ExecuteAsync( + this.ListContainersImpl(prefix, detailsIncluded, currentToken, maxResults, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + + return new ContainerResultSegment(resultSegment.Results, (BlobContinuationToken)resultSegment.ContinuationToken); } /// @@ -218,11 +215,11 @@ public virtual Task GetBlobReferenceFromServerAsync(StorageUri blobU CommonUtility.AssertNotNull("blobUri", blobUri); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetBlobReferenceImpl(blobUri, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -251,24 +248,21 @@ private RESTCommand> ListContainersImpl(string getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => + ListContainersResponse listContainersResponse = new ListContainersResponse(cmd.ResponseStream); + List containersList = listContainersResponse.Containers.Select(item => new CloudBlobContainer(item.Properties, item.Metadata, item.Name, this)).ToList(); + BlobContinuationToken continuationToken = null; + if (listContainersResponse.NextMarker != null) { - ListContainersResponse listContainersResponse = new ListContainersResponse(cmd.ResponseStream); - List containersList = listContainersResponse.Containers.Select(item => new CloudBlobContainer(item.Properties, item.Metadata, item.Name, this)).ToList(); - BlobContinuationToken continuationToken = null; - if (listContainersResponse.NextMarker != null) - { - continuationToken = new BlobContinuationToken() - { - NextMarker = listContainersResponse.NextMarker, - TargetLocation = cmd.CurrentResult.TargetLocation, - }; - } - - return new ResultSegment(containersList) + continuationToken = new BlobContinuationToken() { - ContinuationToken = continuationToken, + NextMarker = listContainersResponse.NextMarker, + TargetLocation = cmd.CurrentResult.TargetLocation, }; + } + + return Task.FromResult(new ResultSegment(containersList) + { + ContinuationToken = continuationToken, }); }; @@ -414,12 +408,11 @@ public virtual Task GetServicePropertiesAsync(BlobRequestOpti BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run( - async () => await Executor.ExecuteAsync( - this.GetServicePropertiesImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServicePropertiesImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand GetServicePropertiesImpl(BlobRequestOptions requestOptions) @@ -435,7 +428,7 @@ private RESTCommand GetServicePropertiesImpl(BlobRequestOptio retCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => BlobHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); + return Task.FromResult(BlobHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); }; requestOptions.ApplyToStorageCommand(retCmd); @@ -479,11 +472,11 @@ public virtual Task SetServicePropertiesAsync(ServiceProperties properties, Blob { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(requestOptions, BlobType.Unspecified, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.SetServicePropertiesImpl(properties, modifiedOptions), + return Executor.ExecuteAsyncNullReturn( + this.SetServicePropertiesImpl(properties, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } private RESTCommand SetServicePropertiesImpl(ServiceProperties properties, BlobRequestOptions requestOptions) @@ -546,12 +539,11 @@ public virtual Task GetServiceStatsAsync(BlobRequestOptions option BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run( - async () => await Executor.ExecuteAsync( - this.GetServiceStatsImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServiceStatsImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand GetServiceStatsImpl(BlobRequestOptions requestOptions) @@ -567,7 +559,7 @@ private RESTCommand GetServiceStatsImpl(BlobRequestOptions request retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => BlobHttpRequestMessageFactory.GetServiceStats(uri, serverTimeout, ctx, this.GetCanonicalizer(), this.Credentials); retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); - retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.Factory.StartNew(() => BlobHttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); + retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.FromResult(BlobHttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); return retCmd; } #endregion diff --git a/Lib/WindowsRuntime/Blob/CloudBlobContainer.cs b/Lib/WindowsRuntime/Blob/CloudBlobContainer.cs index ac8b36877..ea102befd 100644 --- a/Lib/WindowsRuntime/Blob/CloudBlobContainer.cs +++ b/Lib/WindowsRuntime/Blob/CloudBlobContainer.cs @@ -95,11 +95,11 @@ public virtual Task CreateAsync(BlobContainerPublicAccessType accessType, BlobRe } BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateContainerImpl(modifiedOptions, accessType), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -150,7 +150,7 @@ public virtual Task CreateIfNotExistsAsync(BlobContainerPublicAccessType a /// true if the container did not already exist and was created; otherwise false. /// This API requires Create or Write permissions. [DoesServiceRequest] - public virtual Task CreateIfNotExistsAsync(BlobContainerPublicAccessType accessType, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task CreateIfNotExistsAsync(BlobContainerPublicAccessType accessType, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { if (accessType == BlobContainerPublicAccessType.Unknown) { @@ -160,34 +160,31 @@ public virtual Task CreateIfNotExistsAsync(BlobContainerPublicAccessType a BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try - { - await this.CreateAsync(accessType, modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + await this.CreateAsync(accessType, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == BlobErrorCodeStrings.ContainerAlreadyExists)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == BlobErrorCodeStrings.ContainerAlreadyExists)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// @@ -226,11 +223,11 @@ public virtual Task DeleteAsync(AccessCondition accessCondition, BlobRequestOpti public virtual Task DeleteAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteContainerImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -265,55 +262,52 @@ public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, B /// A to observe while waiting for a task to complete. /// true if the container already existed and was deleted; otherwise, false. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try + bool exists = await this.ExistsAsync(true, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + if (!exists) { - bool exists = await this.ExistsAsync(true, modifiedOptions, operationContext, cancellationToken); - if (!exists) - { - return false; - } + return false; } - catch (StorageException e) + } + catch (StorageException e) + { + if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) { - if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) - { - throw; - } + throw; } + } - try - { - await this.DeleteAsync(accessCondition, modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + try + { + await this.DeleteAsync(accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == BlobErrorCodeStrings.ContainerNotFound)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == BlobErrorCodeStrings.ContainerNotFound)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// @@ -421,19 +415,16 @@ public virtual Task ListBlobsSegmentedAsync(string prefix, bo /// A to observe while waiting for a task to complete. /// A result segment containing objects that implement . [DoesServiceRequest] - public virtual Task ListBlobsSegmentedAsync(string prefix, bool useFlatBlobListing, BlobListingDetails blobListingDetails, int? maxResults, BlobContinuationToken currentToken, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task ListBlobsSegmentedAsync(string prefix, bool useFlatBlobListing, BlobListingDetails blobListingDetails, int? maxResults, BlobContinuationToken currentToken, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => - { - ResultSegment resultSegment = await Executor.ExecuteAsync( - this.ListBlobsImpl(prefix, maxResults, useFlatBlobListing, blobListingDetails, modifiedOptions, currentToken), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); + ResultSegment resultSegment = await Executor.ExecuteAsync( + this.ListBlobsImpl(prefix, maxResults, useFlatBlobListing, blobListingDetails, modifiedOptions, currentToken), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); - return new BlobResultSegment(resultSegment.Results, (BlobContinuationToken)resultSegment.ContinuationToken); - }, cancellationToken); + return new BlobResultSegment(resultSegment.Results, (BlobContinuationToken)resultSegment.ContinuationToken); } /// @@ -474,11 +465,11 @@ public virtual Task SetPermissionsAsync(BlobContainerPermissions permissions, Ac public virtual Task SetPermissionsAsync(BlobContainerPermissions permissions, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetPermissionsImpl(permissions, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -516,11 +507,11 @@ public virtual Task GetPermissionsAsync(AccessConditio public virtual Task GetPermissionsAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetPermissionsImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -561,11 +552,11 @@ public virtual Task ExistsAsync(BlobRequestOptions options, OperationConte private Task ExistsAsync(bool primaryOnly, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ExistsImpl(modifiedOptions, primaryOnly), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -603,11 +594,11 @@ public virtual Task FetchAttributesAsync(AccessCondition accessCondition, BlobRe public virtual Task FetchAttributesAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.FetchAttributesImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -645,11 +636,11 @@ public virtual Task SetMetadataAsync(AccessCondition accessCondition, BlobReques public virtual Task SetMetadataAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetMetadataImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -699,11 +690,11 @@ public virtual Task AcquireLeaseAsync(TimeSpan? leaseTime, string propos public virtual Task AcquireLeaseAsync(TimeSpan? leaseTime, string proposedLeaseId, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.AcquireLeaseImpl(leaseTime, proposedLeaseId, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -742,11 +733,11 @@ public virtual Task RenewLeaseAsync(AccessCondition accessCondition, BlobRequest public virtual Task RenewLeaseAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.RenewLeaseImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -788,11 +779,11 @@ public virtual Task ChangeLeaseAsync(string proposedLeaseId, AccessCondi public virtual Task ChangeLeaseAsync(string proposedLeaseId, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ChangeLeaseImpl(proposedLeaseId, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -831,11 +822,11 @@ public virtual Task ReleaseLeaseAsync(AccessCondition accessCondition, BlobReque public virtual Task ReleaseLeaseAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ReleaseLeaseImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -882,11 +873,11 @@ public virtual Task BreakLeaseAsync(TimeSpan? breakPeriod, AccessCondi public virtual Task BreakLeaseAsync(TimeSpan? breakPeriod, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.BreakLeaseImpl(breakPeriod, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1272,12 +1263,9 @@ private RESTCommand GetPermissionsImpl(AccessCondition getCmd.PostProcessResponse = (cmd, resp, ctx) => { this.UpdateETagAndLastModified(resp); - return Task.Factory.StartNew(() => - { - ContainerHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, containerAcl); - this.Properties.PublicAccess = containerAcl.PublicAccess; - return containerAcl; - }); + ContainerHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, containerAcl); + this.Properties.PublicAccess = containerAcl.PublicAccess; + return Task.FromResult(containerAcl); }; return getCmd; @@ -1356,24 +1344,21 @@ private RESTCommand> ListBlobsImpl(string prefix, i getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => + ListBlobsResponse listBlobsResponse = new ListBlobsResponse(cmd.ResponseStream); + List blobList = listBlobsResponse.Blobs.Select(item => this.SelectListBlobItem(item)).ToList(); + BlobContinuationToken continuationToken = null; + if (listBlobsResponse.NextMarker != null) { - ListBlobsResponse listBlobsResponse = new ListBlobsResponse(cmd.ResponseStream); - List blobList = listBlobsResponse.Blobs.Select(item => this.SelectListBlobItem(item)).ToList(); - BlobContinuationToken continuationToken = null; - if (listBlobsResponse.NextMarker != null) - { - continuationToken = new BlobContinuationToken() - { - NextMarker = listBlobsResponse.NextMarker, - TargetLocation = cmd.CurrentResult.TargetLocation, - }; - } - - return new ResultSegment(blobList) + continuationToken = new BlobContinuationToken() { - ContinuationToken = continuationToken, + NextMarker = listBlobsResponse.NextMarker, + TargetLocation = cmd.CurrentResult.TargetLocation, }; + } + + return Task.FromResult(new ResultSegment(blobList) + { + ContinuationToken = continuationToken, }); }; diff --git a/Lib/WindowsRuntime/Blob/CloudBlockBlob.cs b/Lib/WindowsRuntime/Blob/CloudBlockBlob.cs index 3003c3707..5254d0869 100644 --- a/Lib/WindowsRuntime/Blob/CloudBlockBlob.cs +++ b/Lib/WindowsRuntime/Blob/CloudBlockBlob.cs @@ -92,7 +92,7 @@ public virtual Task OpenWriteAsync(AccessCondition accessCondit /// To throw an exception if the blob exists instead of overwriting it, pass in an /// object generated using . /// - public virtual Task OpenWriteAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task OpenWriteAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { this.attributes.AssertNoSnapshot(); operationContext = operationContext ?? new OperationContext(); @@ -100,43 +100,41 @@ public virtual Task OpenWriteAsync(AccessCondition accessCondit if ((accessCondition != null) && accessCondition.IsConditional) { - return Task.Run(async () => + try { - try + // If the accessCondition is IsIfNotExists, the fetch call will always return 400 + await this.FetchAttributesAsync(accessCondition.Clone().RemoveIsIfNotExistsCondition(), options, operationContext, cancellationToken).ConfigureAwait(false); + + // In case the blob already exists and the access condition is "IfNotExists", we should fail fast before uploading any content for the blob + if (accessCondition.IsIfNotExists) { - // If the accessCondition is IsIfNotExists, the fetch call will always return 400 - await this.FetchAttributesAsync(accessCondition.Clone().RemoveIsIfNotExistsCondition(), options, operationContext, cancellationToken); - - // In case the blob already exists and the access condition is "IfNotExists", we should fail fast before uploading any content for the blob - if (accessCondition.IsIfNotExists) - { - throw GenerateExceptionForConflictFailure(); - } + throw GenerateExceptionForConflictFailure(); } - catch (Exception) + } + catch (Exception) + { + if ((operationContext.LastResult != null) && + (((operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) && + string.IsNullOrEmpty(accessCondition.IfMatchETag)) || + (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Forbidden))) { - if ((operationContext.LastResult != null) && - (((operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) && - string.IsNullOrEmpty(accessCondition.IfMatchETag)) || - (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Forbidden))) - { - // If we got a 404 and the condition was not an If-Match OR if we got a 403, - // we should continue with the operation. - } - else - { - throw; - } + // If we got a 404 and the condition was not an If-Match OR if we got a 403, + // we should continue with the operation. } + else + { + throw; + } + } + + CloudBlobStream stream = new BlobWriteStream(this, accessCondition, modifiedOptions, operationContext); + return stream; - CloudBlobStream stream = new BlobWriteStream(this, accessCondition, modifiedOptions, operationContext); - return stream; - }, cancellationToken); } else { CloudBlobStream stream = new BlobWriteStream(this, accessCondition, modifiedOptions, operationContext); - return Task.FromResult(stream); + return stream; } } @@ -249,7 +247,7 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCon /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + internal async Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("source", source); @@ -270,60 +268,58 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCon operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => + bool lessThanSingleBlobThreshold = sourceAsStream.CanSeek + && (length ?? sourceAsStream.Length - sourceAsStream.Position) + <= modifiedOptions.SingleBlobUploadThresholdInBytes; + if (modifiedOptions.ParallelOperationThreadCount == 1 && lessThanSingleBlobThreshold) { - bool lessThanSingleBlobThreshold = sourceAsStream.CanSeek - && (length ?? sourceAsStream.Length - sourceAsStream.Position) - <= modifiedOptions.SingleBlobUploadThresholdInBytes; - if (modifiedOptions.ParallelOperationThreadCount == 1 && lessThanSingleBlobThreshold) + string contentMD5 = null; + if (modifiedOptions.StoreBlobContentMD5.Value) { - string contentMD5 = null; - if (modifiedOptions.StoreBlobContentMD5.Value) - { - StreamDescriptor streamCopyState = new StreamDescriptor(); - long startPosition = sourceAsStream.Position; - await sourceAsStream.WriteToAsync(Stream.Null, length, null /* maxLength */, true, tempExecutionState, streamCopyState, cancellationToken); - sourceAsStream.Position = startPosition; - contentMD5 = streamCopyState.Md5; - } - else - { - if (modifiedOptions.UseTransactionalMD5.Value) - { - throw new ArgumentException(SR.PutBlobNeedsStoreBlobContentMD5, "options"); - } - } - - await Executor.ExecuteAsyncNullReturn( - this.PutBlobImpl(sourceAsStream, length, contentMD5, accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); + StreamDescriptor streamCopyState = new StreamDescriptor(); + long startPosition = sourceAsStream.Position; + await sourceAsStream.WriteToAsync(Stream.Null, length, null /* maxLength */, true, tempExecutionState, streamCopyState, cancellationToken).ConfigureAwait(false); + sourceAsStream.Position = startPosition; + contentMD5 = streamCopyState.Md5; } else { - bool useOpenWrite = !source.CanSeek - || this.streamWriteSizeInBytes < Constants.MinLargeBlockSize - || (modifiedOptions.StoreBlobContentMD5.HasValue && modifiedOptions.StoreBlobContentMD5.Value); - - if (useOpenWrite) + if (modifiedOptions.UseTransactionalMD5.Value) { - using (CloudBlobStream blobStream = await this.OpenWriteAsync(accessCondition, options, operationContext, cancellationToken)) - { - // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our - // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. - await sourceAsStream.WriteToAsync(blobStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken); - await blobStream.CommitAsync(); - } + throw new ArgumentException(SR.PutBlobNeedsStoreBlobContentMD5, "options"); } - else + } + + await Executor.ExecuteAsyncNullReturn( + this.PutBlobImpl(sourceAsStream, length, contentMD5, accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + } + else + { + bool useOpenWrite = !source.CanSeek + || this.streamWriteSizeInBytes < Constants.MinLargeBlockSize + || (modifiedOptions.StoreBlobContentMD5.HasValue && modifiedOptions.StoreBlobContentMD5.Value); + + if (useOpenWrite) + { + using (CloudBlobStream blobStream = await this.OpenWriteAsync(accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false)) { - // Synchronization mutex required to ensure thread-safe, concurrent operations on related SubStream instances. - SemaphoreSlim streamReadThrottler = new SemaphoreSlim(1); - await this.UploadFromMultiStreamAsync(this.OpenMultiSubStream(source, length, streamReadThrottler), accessCondition, modifiedOptions, operationContext, cancellationToken); + // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our + // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. + await sourceAsStream.WriteToAsync(blobStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken).ConfigureAwait(false); + await blobStream.CommitAsync().ConfigureAwait(false); } } - }, cancellationToken); + else + { + // Synchronization mutex required to ensure thread-safe, concurrent operations on related SubStream instances. + SemaphoreSlim streamReadThrottler = new SemaphoreSlim(1); + await this.UploadFromMultiStreamAsync(this.OpenMultiSubStream(source, length, streamReadThrottler), accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + } + } + } /// @@ -386,13 +382,10 @@ public virtual Task UploadFromFileAsync(StorageFile source, AccessCondition acce { CommonUtility.AssertNotNull("source", source); - return Task.Run(async () => + using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken).ConfigureAwait(false)) { - using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken)) - { - await this.UploadFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken); - } - }); + await this.UploadFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -407,31 +400,28 @@ public virtual Task UploadFromFileAsync(StorageFile source, AccessCondition acce /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task UploadFromFileAsync(string path, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task UploadFromFileAsync(string path, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - CommonUtility.AssertNotNull("path", path); - - return Task.Run(async () => - { - BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.BlockBlob, this.ServiceClient); + CommonUtility.AssertNotNull("path", path); - // Determines whether to use the normal, single-stream upload approach or the new parallel, multi-stream strategy. - bool useSingleStream = this.streamWriteSizeInBytes < Constants.MinLargeBlockSize - || (modifiedOptions.StoreBlobContentMD5.HasValue && modifiedOptions.StoreBlobContentMD5.Value); + BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.BlockBlob, this.ServiceClient); - if (useSingleStream) - { - using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - await this.UploadFromStreamAsync(stream, accessCondition, modifiedOptions, operationContext, cancellationToken); - } - } - else + // Determines whether to use the normal, single-stream upload approach or the new parallel, multi-stream strategy. + bool useSingleStream = this.streamWriteSizeInBytes < Constants.MinLargeBlockSize + || (modifiedOptions.StoreBlobContentMD5.HasValue && modifiedOptions.StoreBlobContentMD5.Value); + + if (useSingleStream) + { + using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { - CheckAdjustBlockSize(new FileInfo(path).Length); - await this.UploadFromMultiStreamAsync(OpenMultiFileStream(path), accessCondition, modifiedOptions, operationContext, cancellationToken); + await this.UploadFromStreamAsync(stream, accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); } - }, cancellationToken); + } + else + { + CheckAdjustBlockSize(new FileInfo(path).Length); + await this.UploadFromMultiStreamAsync(OpenMultiFileStream(path), accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -589,17 +579,14 @@ public virtual Task DownloadTextAsync(Encoding encoding, AccessCondition /// A to observe while waiting for a task to complete. /// The contents of the blob, as a string. [DoesServiceRequest] - public virtual Task DownloadTextAsync(Encoding encoding, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadTextAsync(Encoding encoding, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => + using (SyncMemoryStream stream = new SyncMemoryStream()) { - using (SyncMemoryStream stream = new SyncMemoryStream()) - { - await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - byte[] streamAsBytes = stream.ToArray(); - return (encoding ?? Encoding.UTF8).GetString(streamAsBytes, 0, streamAsBytes.Length); - } - }, cancellationToken); + await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + byte[] streamAsBytes = stream.ToArray(); + return (encoding ?? Encoding.UTF8).GetString(streamAsBytes, 0, streamAsBytes.Length); + } } /// @@ -640,11 +627,11 @@ public virtual Task CreateSnapshotAsync(IDictionary await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.CreateSnapshotImpl(metadata, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -691,60 +678,57 @@ public virtual Task PutBlockAsync(string blockId, Stream blockData, string conte /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task PutBlockAsync(string blockId, Stream blockData, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task PutBlockAsync(string blockId, Stream blockData, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.BlockBlob, this.ServiceClient); bool requiresContentMD5 = string.IsNullOrEmpty(contentMD5) && modifiedOptions.UseTransactionalMD5.Value; operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => - { - Stream blockDataAsStream = blockData; - Stream seekableStream = blockDataAsStream; - bool seekableStreamCreated = false; + Stream blockDataAsStream = blockData; + Stream seekableStream = blockDataAsStream; + bool seekableStreamCreated = false; - try + try + { + if (!blockDataAsStream.CanSeek || requiresContentMD5) { - if (!blockDataAsStream.CanSeek || requiresContentMD5) + Stream writeToStream; + if (blockDataAsStream.CanSeek) + { + writeToStream = Stream.Null; + } + else { - Stream writeToStream; - if (blockDataAsStream.CanSeek) - { - writeToStream = Stream.Null; - } - else - { - seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); - seekableStreamCreated = true; - writeToStream = seekableStream; - } - - StreamDescriptor streamCopyState = new StreamDescriptor(); - long startPosition = seekableStream.Position; - await blockDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken); - seekableStream.Position = startPosition; - - if (requiresContentMD5) - { - contentMD5 = streamCopyState.Md5; - } + seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); + seekableStreamCreated = true; + writeToStream = seekableStream; } - await Executor.ExecuteAsyncNullReturn( - this.PutBlockImpl(seekableStream, blockId, contentMD5, accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - } - finally - { - if (seekableStreamCreated) + StreamDescriptor streamCopyState = new StreamDescriptor(); + long startPosition = seekableStream.Position; + await blockDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken).ConfigureAwait(false); + seekableStream.Position = startPosition; + + if (requiresContentMD5) { - seekableStream.Dispose(); + contentMD5 = streamCopyState.Md5; } } - }, cancellationToken); + + await Executor.ExecuteAsyncNullReturn( + this.PutBlockImpl(seekableStream, blockId, contentMD5, accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + } + finally + { + if (seekableStreamCreated) + { + seekableStream.Dispose(); + } + } } /// @@ -786,11 +770,11 @@ public virtual Task PutBlockListAsync(IEnumerable blockList, AccessCondi { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.BlockBlob, this.ServiceClient); IEnumerable items = blockList.Select(i => new PutBlockListItem(i, BlockSearchMode.Latest)); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.PutBlockListImpl(items, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -832,11 +816,11 @@ public virtual Task> DownloadBlockListAsync(BlockList public virtual Task> DownloadBlockListAsync(BlockListingFilter blockListingFilter, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.BlockBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetBlockListImpl(blockListingFilter, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -988,11 +972,11 @@ public virtual Task SetStandardBlobTierAsync(StandardBlobTier standardBlobTier, { this.attributes.AssertNoSnapshot(); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.BlockBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.SetStandardBlobTierImpl(standardBlobTier, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1168,12 +1152,9 @@ internal RESTCommand> GetBlockListImpl(BlockListingFi getCmd.PostProcessResponse = (cmd, resp, ctx) => { CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, true); - return Task.Factory.StartNew(() => - { - GetBlockListResponse responseParser = new GetBlockListResponse(cmd.ResponseStream); - IEnumerable blocks = new List(responseParser.Blocks); - return blocks; - }); + GetBlockListResponse responseParser = new GetBlockListResponse(cmd.ResponseStream); + IEnumerable blocks = new List(responseParser.Blocks); + return Task.FromResult(blocks); }; return getCmd; diff --git a/Lib/WindowsRuntime/Blob/CloudPageBlob.cs b/Lib/WindowsRuntime/Blob/CloudPageBlob.cs index 6ca7e7d61..dd77a91cd 100644 --- a/Lib/WindowsRuntime/Blob/CloudPageBlob.cs +++ b/Lib/WindowsRuntime/Blob/CloudPageBlob.cs @@ -107,7 +107,7 @@ public virtual Task OpenWriteAsync(long? size, AccessCondition /// object generated using . /// [DoesServiceRequest] - internal virtual Task OpenWriteAsync(long? size, PremiumPageBlobTier? premiumPageBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + internal virtual async Task OpenWriteAsync(long? size, PremiumPageBlobTier? premiumPageBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { this.attributes.AssertNoSnapshot(); bool createNew = size.HasValue; @@ -117,26 +117,23 @@ internal virtual Task OpenWriteAsync(long? size, PremiumPageBlo throw new ArgumentException(SR.MD5NotPossible); } - return Task.Run(async () => + if (createNew) { - if (createNew) - { - await this.CreateAsync(size.Value, premiumPageBlobTier, accessCondition, options, operationContext, cancellationToken); - } - else - { - await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken); - size = this.Properties.Length; - } + await this.CreateAsync(size.Value, premiumPageBlobTier, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } + else + { + await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + size = this.Properties.Length; + } - if (accessCondition != null) - { - accessCondition = AccessCondition.GenerateLeaseCondition(accessCondition.LeaseId); - } + if (accessCondition != null) + { + accessCondition = AccessCondition.GenerateLeaseCondition(accessCondition.LeaseId); + } - CloudBlobStream stream = new BlobWriteStream(this, size.Value, createNew, accessCondition, modifiedOptions, operationContext); - return stream; - }, cancellationToken); + CloudBlobStream stream = new BlobWriteStream(this, size.Value, createNew, accessCondition, modifiedOptions, operationContext); + return stream; } /// @@ -281,7 +278,7 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCon /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - internal Task UploadFromStreamAsyncHelper(Stream source, long? length, PremiumPageBlobTier? premiumPageBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + internal async Task UploadFromStreamAsyncHelper(Stream source, long? length, PremiumPageBlobTier? premiumPageBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("source", source); @@ -310,16 +307,13 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, PremiumPa throw new ArgumentException(SR.InvalidPageSize, "source"); } - return Task.Run(async () => + using (CloudBlobStream blobStream = await this.OpenWriteAsync(length, premiumPageBlobTier, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false)) { - using (CloudBlobStream blobStream = await this.OpenWriteAsync(length, premiumPageBlobTier, accessCondition, options, operationContext, cancellationToken)) - { - // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our - // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. - await sourceAsStream.WriteToAsync(blobStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken); - await blobStream.CommitAsync(); - } - }, cancellationToken); + // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our + // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. + await sourceAsStream.WriteToAsync(blobStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken).ConfigureAwait(false); + await blobStream.CommitAsync().ConfigureAwait(false); + } } /// @@ -399,13 +393,10 @@ public virtual Task UploadFromFileAsync(StorageFile source, PremiumPageBlobTier? { CommonUtility.AssertNotNull("source", source); - return Task.Run(async () => + using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken).ConfigureAwait(false)) { - using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken)) - { - await this.UploadFromStreamAsync(stream.AsStream(), premiumBlobTier, accessCondition, options, operationContext, cancellationToken); - } - }); + await this.UploadFromStreamAsync(stream.AsStream(), premiumBlobTier, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif #if NETCORE @@ -435,17 +426,14 @@ public virtual Task UploadFromFileAsync(string path, AccessCondition accessCondi /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task UploadFromFileAsync(string path, PremiumPageBlobTier? premiumBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task UploadFromFileAsync(string path, PremiumPageBlobTier? premiumBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("path", path); - return Task.Run(async () => + using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { - using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - await this.UploadFromStreamAsync(stream, premiumBlobTier, accessCondition, options, operationContext, cancellationToken); - } - }, cancellationToken); + await this.UploadFromStreamAsync(stream, premiumBlobTier, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -574,11 +562,11 @@ public virtual Task CreateAsync(long size, AccessCondition accessCondition, Blob public virtual Task CreateAsync(long size, PremiumPageBlobTier? premiumBlobTier, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateImpl(size, premiumBlobTier, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -619,11 +607,11 @@ public virtual Task ResizeAsync(long size, AccessCondition accessCondition, Blob public virtual Task ResizeAsync(long size, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ResizeImpl(size, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -667,11 +655,11 @@ public virtual Task SetSequenceNumberAsync(SequenceNumberAction sequenceNumberAc public virtual Task SetSequenceNumberAsync(SequenceNumberAction sequenceNumberAction, long? sequenceNumber, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetSequenceNumberImpl(sequenceNumberAction, sequenceNumber, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -713,11 +701,11 @@ public virtual Task> GetPageRangesAsync(long? offset, lon public virtual Task> GetPageRangesAsync(long? offset, long? length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetPageRangesImpl(offset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -762,11 +750,11 @@ public virtual Task> GetPageRangesDiffAsync(DateTimeO public virtual Task> GetPageRangesDiffAsync(DateTimeOffset previousSnapshotTime, long? offset, long? length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetPageRangesDiffImpl(previousSnapshotTime, offset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -807,11 +795,11 @@ public virtual Task CreateSnapshotAsync(IDictionary await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.CreateSnapshotImpl(metadata, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -858,59 +846,56 @@ public virtual Task WritePagesAsync(Stream pageData, long startOffset, string co /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task WritePagesAsync(Stream pageData, long startOffset, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task WritePagesAsync(Stream pageData, long startOffset, string contentMD5, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); bool requiresContentMD5 = (contentMD5 == null) && modifiedOptions.UseTransactionalMD5.Value; operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => - { - Stream pageDataAsStream = pageData; - Stream seekableStream = pageDataAsStream; - bool seekableStreamCreated = false; + Stream pageDataAsStream = pageData; + Stream seekableStream = pageDataAsStream; + bool seekableStreamCreated = false; - try + try + { + if (!pageDataAsStream.CanSeek || requiresContentMD5) { - if (!pageDataAsStream.CanSeek || requiresContentMD5) + Stream writeToStream; + if (pageDataAsStream.CanSeek) { - Stream writeToStream; - if (pageDataAsStream.CanSeek) - { - writeToStream = Stream.Null; - } - else - { - seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); - seekableStreamCreated = true; - writeToStream = seekableStream; - } - - StreamDescriptor streamCopyState = new StreamDescriptor(); - long startPosition = seekableStream.Position; - await pageDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken); - seekableStream.Position = startPosition; - - if (requiresContentMD5) - { - contentMD5 = streamCopyState.Md5; - } + writeToStream = Stream.Null; + } + else + { + seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); + seekableStreamCreated = true; + writeToStream = seekableStream; } - await Executor.ExecuteAsyncNullReturn( - this.PutPageImpl(seekableStream, startOffset, contentMD5, accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - } - finally - { - if (seekableStreamCreated) + StreamDescriptor streamCopyState = new StreamDescriptor(); + long startPosition = seekableStream.Position; + await pageDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken).ConfigureAwait(false); + seekableStream.Position = startPosition; + + if (requiresContentMD5) { - seekableStream.Dispose(); + contentMD5 = streamCopyState.Md5; } } - }, cancellationToken); + + await Executor.ExecuteAsyncNullReturn( + this.PutPageImpl(seekableStream, startOffset, contentMD5, accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + } + finally + { + if (seekableStreamCreated) + { + seekableStream.Dispose(); + } + } } /// @@ -954,11 +939,11 @@ public virtual Task ClearPagesAsync(long startOffset, long length, AccessConditi public virtual Task ClearPagesAsync(long startOffset, long length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ClearPageImpl(startOffset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1103,11 +1088,11 @@ public virtual Task StartIncrementalCopyAsync(Uri sourceSnapshot, Access { CommonUtility.AssertNotNull("sourceSnapshot", sourceSnapshot); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.Unspecified, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.StartCopyImpl(this.attributes, sourceSnapshot, true /*incrementalCopy */, null /* pageBlobTier */, null /* sourceAccessCondition */, destAccessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1147,11 +1132,11 @@ public virtual Task SetPremiumBlobTierAsync(PremiumPageBlobTier premiumBlobTier, { this.attributes.AssertNoSnapshot(); BlobRequestOptions modifiedOptions = BlobRequestOptions.ApplyDefaults(options, BlobType.PageBlob, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.SetBlobTierImpl(premiumBlobTier, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1302,12 +1287,9 @@ private RESTCommand> GetPageRangesImpl(long? offset, long getCmd.PostProcessResponse = (cmd, resp, ctx) => { CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, true); - return Task.Factory.StartNew(() => - { - GetPageRangesResponse getPageRangesResponse = new GetPageRangesResponse(cmd.ResponseStream); - IEnumerable pageRanges = new List(getPageRangesResponse.PageRanges); - return pageRanges; - }); + GetPageRangesResponse getPageRangesResponse = new GetPageRangesResponse(cmd.ResponseStream); + IEnumerable pageRanges = new List(getPageRangesResponse.PageRanges); + return Task.FromResult(pageRanges); }; return getCmd; @@ -1339,12 +1321,9 @@ private RESTCommand> GetPageRangesDiffImpl(DateTimeOf getCmd.PostProcessResponse = (cmd, resp, ctx) => { CloudBlob.UpdateETagLMTLengthAndSequenceNumber(this.attributes, resp, true); - return Task.Factory.StartNew(() => - { - GetPageDiffRangesResponse getPageDiffRangesResponse = new GetPageDiffRangesResponse(cmd.ResponseStream); - IEnumerable pageDiffRanges = new List(getPageDiffRangesResponse.PageDiffRanges); - return pageDiffRanges; - }); + GetPageDiffRangesResponse getPageDiffRangesResponse = new GetPageDiffRangesResponse(cmd.ResponseStream); + IEnumerable pageDiffRanges = new List(getPageDiffRangesResponse.PageDiffRanges); + return Task.FromResult(pageDiffRanges); }; return getCmd; diff --git a/Lib/WindowsRuntime/Core/Executor/Executor.cs b/Lib/WindowsRuntime/Core/Executor/Executor.cs index c974212be..a99b3dc8e 100644 --- a/Lib/WindowsRuntime/Core/Executor/Executor.cs +++ b/Lib/WindowsRuntime/Core/Executor/Executor.cs @@ -130,14 +130,14 @@ private async static Task ExecuteAsyncInternal(RESTCommand cmd, IRetryP // Send Request executionState.CurrentOperation = ExecutorOperation.BeginGetResponse; Logger.LogInformational(executionState.OperationContext, SR.TraceGetResponse); - executionState.Resp = await client.SendAsync(executionState.Req, HttpCompletionOption.ResponseHeadersRead, timeoutTokenSource.Token); + executionState.Resp = await client.SendAsync(executionState.Req, HttpCompletionOption.ResponseHeadersRead, timeoutTokenSource.Token).ConfigureAwait(false); executionState.CurrentOperation = ExecutorOperation.EndGetResponse; // Since HttpClient wont throw for non success, manually check and populate an exception if (!executionState.Resp.IsSuccessStatusCode) { // At this point, don't try to read the stream to parse the error - executionState.ExceptionRef = await Exceptions.PopulateStorageExceptionFromHttpResponseMessage(executionState.Resp, executionState.Cmd.CurrentResult, executionState.Cmd.ParseError); + executionState.ExceptionRef = await Exceptions.PopulateStorageExceptionFromHttpResponseMessage(executionState.Resp, executionState.Cmd.CurrentResult, executionState.Cmd.ParseError).ConfigureAwait(false); } Logger.LogInformational(executionState.OperationContext, SR.TraceResponse, executionState.Cmd.CurrentResult.HttpStatusCode, executionState.Cmd.CurrentResult.ServiceRequestID, executionState.Cmd.CurrentResult.ContentMd5, executionState.Cmd.CurrentResult.Etag); @@ -165,7 +165,7 @@ private async static Task ExecuteAsyncInternal(RESTCommand cmd, IRetryP // 8. (Potentially reads stream from server) executionState.CurrentOperation = ExecutorOperation.GetResponseStream; - cmd.ResponseStream = await executionState.Resp.Content.ReadAsStreamAsync(); + cmd.ResponseStream = await executionState.Resp.Content.ReadAsStreamAsync().ConfigureAwait(false); // The stream is now available in ResponseStream. Use the stream to parse out the response or error if (executionState.ExceptionRef != null) @@ -176,7 +176,7 @@ private async static Task ExecuteAsyncInternal(RESTCommand cmd, IRetryP try { cmd.ErrorStream = new MemoryStream(); - await cmd.ResponseStream.WriteToAsync(cmd.ErrorStream, null /* copyLength */, null /* maxLength */, false, executionState, new StreamDescriptor(), timeoutTokenSource.Token); + await cmd.ResponseStream.WriteToAsync(cmd.ErrorStream, null /* copyLength */, null /* maxLength */, false, executionState, new StreamDescriptor(), timeoutTokenSource.Token).ConfigureAwait(false); cmd.ErrorStream.Seek(0, SeekOrigin.Begin); #if NETCORE executionState.ExceptionRef = StorageException.TranslateExceptionWithPreBufferedStream(executionState.ExceptionRef, executionState.Cmd.CurrentResult, stream => executionState.Cmd.ParseError(stream, executionState.Resp, null), cmd.ErrorStream, executionState.Resp); @@ -212,7 +212,7 @@ private async static Task ExecuteAsyncInternal(RESTCommand cmd, IRetryP { executionState.CurrentOperation = ExecutorOperation.BeginDownloadResponse; Logger.LogInformational(executionState.OperationContext, SR.TraceDownload); - await cmd.ResponseStream.WriteToAsync(cmd.DestinationStream, null /* copyLength */, null /* maxLength */, cmd.CalculateMd5ForResponseStream, executionState, cmd.StreamCopyState, timeoutTokenSource.Token); + await cmd.ResponseStream.WriteToAsync(cmd.DestinationStream, null /* copyLength */, null /* maxLength */, cmd.CalculateMd5ForResponseStream, executionState, cmd.StreamCopyState, timeoutTokenSource.Token).ConfigureAwait(false); } finally { @@ -227,7 +227,7 @@ private async static Task ExecuteAsyncInternal(RESTCommand cmd, IRetryP { executionState.CurrentOperation = ExecutorOperation.PostProcess; Logger.LogInformational(executionState.OperationContext, SR.TracePostProcess); - executionState.Result = await cmd.PostProcessResponse(cmd, executionState.Resp, executionState.OperationContext); + executionState.Result = await cmd.PostProcessResponse(cmd, executionState.Resp, executionState.OperationContext).ConfigureAwait(false); } executionState.CurrentOperation = ExecutorOperation.EndOperation; @@ -320,7 +320,7 @@ private async static Task ExecuteAsyncInternal(RESTCommand cmd, IRetryP if (delay > TimeSpan.Zero) { - await Task.Delay(delay, token); + await Task.Delay(delay, token).ConfigureAwait(false); } Logger.LogInformational(executionState.OperationContext, SR.TraceRetry); diff --git a/Lib/WindowsRuntime/File/CloudFile.cs b/Lib/WindowsRuntime/File/CloudFile.cs index 0a581d9b0..4782279b7 100644 --- a/Lib/WindowsRuntime/File/CloudFile.cs +++ b/Lib/WindowsRuntime/File/CloudFile.cs @@ -75,16 +75,13 @@ public virtual Task OpenReadAsync(AccessCondition accessCondition, FileR /// A to observe while waiting for a task to complete. /// A stream to be used for reading from the file. [DoesServiceRequest] - public virtual Task OpenReadAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task OpenReadAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => - { - await this.FetchAttributesAsync(accessCondition, options, operationContext); - AccessCondition streamAccessCondition = AccessCondition.CloneConditionWithETag(accessCondition, this.Properties.ETag); - FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient, false); - return new FileReadStream(this, streamAccessCondition, modifiedOptions, operationContext); - }, cancellationToken); + await this.FetchAttributesAsync(accessCondition, options, operationContext).ConfigureAwait(false); + AccessCondition streamAccessCondition = AccessCondition.CloneConditionWithETag(accessCondition, this.Properties.ETag); + FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient, false); + return new FileReadStream(this, streamAccessCondition, modifiedOptions, operationContext); } /// @@ -122,7 +119,7 @@ public virtual Task OpenWriteAsync(long? size, AccessCondition /// A to observe while waiting for a task to complete. /// A stream to be used for writing to the file. [DoesServiceRequest] - public virtual Task OpenWriteAsync(long? size, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task OpenWriteAsync(long? size, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { this.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient, false); @@ -133,26 +130,23 @@ public virtual Task OpenWriteAsync(long? size, AccessCondition { throw new ArgumentException(SR.MD5NotPossible); } - return Task.Run(async () => + if (createNew) { - if (createNew) - { - await this.CreateAsync(size.Value, accessCondition, options, operationContext, cancellationToken); - } - else - { - await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken); - size = this.Properties.Length; - } + await this.CreateAsync(size.Value, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } + else + { + await this.FetchAttributesAsync(accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + size = this.Properties.Length; + } - if (accessCondition != null) - { - accessCondition = AccessCondition.GenerateLeaseCondition(accessCondition.LeaseId); - } + if (accessCondition != null) + { + accessCondition = AccessCondition.GenerateLeaseCondition(accessCondition.LeaseId); + } - CloudFileStream stream = new FileWriteStream(this, size.Value, createNew, accessCondition, modifiedOptions, operationContext); - return stream; - }, cancellationToken); + CloudFileStream stream = new FileWriteStream(this, size.Value, createNew, accessCondition, modifiedOptions, operationContext); + return stream; } /// @@ -264,7 +258,7 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCon /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + internal async Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("source", source); @@ -288,16 +282,14 @@ internal Task UploadFromStreamAsyncHelper(Stream source, long? length, AccessCon operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => + using (CloudFileStream fileStream = await this.OpenWriteAsync(length, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false)) { - using (CloudFileStream fileStream = await this.OpenWriteAsync(length, accessCondition, options, operationContext, cancellationToken)) - { - // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our - // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. - await sourceAsStream.WriteToAsync(fileStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken); - await fileStream.CommitAsync(); - } - }, cancellationToken); + // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our + // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. + await sourceAsStream.WriteToAsync(fileStream, length, null /* maxLength */, false, tempExecutionState, null /* streamCopyState */, cancellationToken).ConfigureAwait(false); + await fileStream.CommitAsync().ConfigureAwait(false); + } + } /// @@ -361,13 +353,10 @@ public virtual Task UploadFromFileAsync(StorageFile source, AccessCondition acce { CommonUtility.AssertNotNull("source", source); - return Task.Run(async () => + using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken).ConfigureAwait(false)) { - using (IRandomAccessStreamWithContentType stream = await source.OpenReadAsync().AsTask(cancellationToken)) - { - await this.UploadFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken); - } - }); + await this.UploadFromStreamAsync(stream.AsStream(), accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -382,17 +371,14 @@ public virtual Task UploadFromFileAsync(StorageFile source, AccessCondition acce /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task UploadFromFileAsync(string path, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task UploadFromFileAsync(string path, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("path", path); - return Task.Run(async () => + using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { - using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) - { - await this.UploadFromStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - } - }, cancellationToken); + await this.UploadFromStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + } } #endif @@ -591,14 +577,11 @@ public virtual Task DownloadToFileAsync(StorageFile target, AccessCondition acce { CommonUtility.AssertNotNull("target", target); - return Task.Run(async () => + using (StorageStreamTransaction transaction = await target.OpenTransactedWriteAsync().AsTask(cancellationToken).ConfigureAwait(false)) { - using (StorageStreamTransaction transaction = await target.OpenTransactedWriteAsync().AsTask(cancellationToken)) - { - await this.DownloadToStreamAsync(transaction.Stream.AsStream(), accessCondition, options, operationContext, cancellationToken); - await transaction.CommitAsync(); - } - }); + await this.DownloadToStreamAsync(transaction.Stream.AsStream(), accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + await transaction.CommitAsync().ConfigureAwait(false); + } } #endif @@ -614,39 +597,36 @@ public virtual Task DownloadToFileAsync(StorageFile target, AccessCondition acce /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. [DoesServiceRequest] - public virtual Task DownloadToFileAsync(string path, FileMode mode, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadToFileAsync(string path, FileMode mode, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("path", path); - return Task.Run(async () => - { - FileStream stream = new FileStream(path, mode, FileAccess.Write); + FileStream stream = new FileStream(path, mode, FileAccess.Write); - try + try + { + using (stream) { - using (stream) - { - await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - } + await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); } - catch (Exception) + } + catch (Exception) + { + if (mode == FileMode.Create || mode == FileMode.CreateNew) { - if (mode == FileMode.Create || mode == FileMode.CreateNew) + try { - try - { - File.Delete(path); - } - catch (Exception) - { - // Best effort to clean up in the event that download was unsuccessful. - // Do not throw as we want to throw original exception. - } + File.Delete(path); + } + catch (Exception) + { + // Best effort to clean up in the event that download was unsuccessful. + // Do not throw as we want to throw original exception. } - - throw; } - }); + + throw; + } } #endif @@ -738,17 +718,14 @@ public virtual Task DownloadTextAsync(AccessCondition accessCondition, F /// A to observe while waiting for a task to complete. /// The contents of the file, as a string. [DoesServiceRequest] - public virtual Task DownloadTextAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadTextAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => + using (SyncMemoryStream stream = new SyncMemoryStream()) { - using (SyncMemoryStream stream = new SyncMemoryStream()) - { - await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken); - byte[] streamAsBytes = stream.ToArray(); - return Encoding.UTF8.GetString(streamAsBytes, 0, streamAsBytes.Length); - } - }, cancellationToken); + await this.DownloadToStreamAsync(stream, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + byte[] streamAsBytes = stream.ToArray(); + return Encoding.UTF8.GetString(streamAsBytes, 0, streamAsBytes.Length); + } } /// @@ -787,11 +764,11 @@ public virtual Task DownloadRangeToStreamAsync(Stream target, long? offset, long // We should always call AsStreamForWrite with bufferSize=0 to prevent buffering. Our // stream copier only writes 64K buffers at a time anyway, so no buffering is needed. - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.GetFileImpl(target, offset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -838,16 +815,13 @@ public virtual Task DownloadRangeToByteArrayAsync(byte[] target, int index, /// A to observe while waiting for a task to complete. /// The total number of bytes read into the buffer. [DoesServiceRequest] - public virtual Task DownloadRangeToByteArrayAsync(byte[] target, int index, long? fileOffset, long? length, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DownloadRangeToByteArrayAsync(byte[] target, int index, long? fileOffset, long? length, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => + using (SyncMemoryStream stream = new SyncMemoryStream(target, index)) { - using (SyncMemoryStream stream = new SyncMemoryStream(target, index)) - { - await this.DownloadRangeToStreamAsync(stream, fileOffset, length, accessCondition, options, operationContext, cancellationToken); - return (int)stream.Position; - } - }, cancellationToken); + await this.DownloadRangeToStreamAsync(stream, fileOffset, length, accessCondition, options, operationContext, cancellationToken).ConfigureAwait(false); + return (int)stream.Position; + } } /// @@ -886,11 +860,11 @@ public virtual Task CreateAsync(long size, AccessCondition accessCondition, File { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateImpl(size, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -926,11 +900,11 @@ public virtual Task ExistsAsync(FileRequestOptions options, OperationConte public virtual Task ExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ExistsImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -965,11 +939,11 @@ public virtual Task FetchAttributesAsync(AccessCondition accessCondition, FileRe public virtual Task FetchAttributesAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.FetchAttributesImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1005,11 +979,11 @@ public virtual Task DeleteAsync(AccessCondition accessCondition, FileRequestOpti public virtual Task DeleteAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteFileImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1044,39 +1018,36 @@ public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, F /// A to observe while waiting for a task to complete. /// true if the file already existed and was deleted; otherwise, false. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try - { - await this.DeleteAsync(accessCondition, modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + await this.DeleteAsync(accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == StorageErrorCodeStrings.ResourceNotFound)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == StorageErrorCodeStrings.ResourceNotFound)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// Gets a collection of valid ranges and their starting and ending bytes. @@ -1118,11 +1089,11 @@ public virtual Task> ListRangesAsync(long? offset, long? public virtual Task> ListRangesAsync(long? offset, long? length, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ListRangesImpl(offset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1157,11 +1128,11 @@ public virtual Task SetPropertiesAsync(AccessCondition accessCondition, FileRequ public virtual Task SetPropertiesAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetPropertiesImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1199,11 +1170,11 @@ public virtual Task ResizeAsync(long size, AccessCondition accessCondition, File public virtual Task ResizeAsync(long size, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ResizeImpl(size, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1239,11 +1210,11 @@ public virtual Task SetMetadataAsync(AccessCondition accessCondition, FileReques { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetMetadataImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1289,7 +1260,7 @@ public virtual Task WriteRangeAsync(Stream rangeData, long startOffset, string c /// An object that represents the context for the current operation. /// A to observe while waiting for a task to complete. /// A that represents an asynchronous action. - public virtual Task WriteRangeAsync(Stream rangeData, long startOffset, string contentMD5, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task WriteRangeAsync(Stream rangeData, long startOffset, string contentMD5, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("rangeData", rangeData); @@ -1299,60 +1270,57 @@ public virtual Task WriteRangeAsync(Stream rangeData, long startOffset, string c operationContext = operationContext ?? new OperationContext(); ExecutionState tempExecutionState = CommonUtility.CreateTemporaryExecutionState(modifiedOptions); - return Task.Run(async () => - { - DateTime streamCopyStartTime = DateTime.Now; + DateTime streamCopyStartTime = DateTime.Now; - Stream rangeDataAsStream = rangeData; - Stream seekableStream = rangeDataAsStream; - bool seekableStreamCreated = false; + Stream rangeDataAsStream = rangeData; + Stream seekableStream = rangeDataAsStream; + bool seekableStreamCreated = false; - try + try + { + if (!rangeDataAsStream.CanSeek || requiresContentMD5) { - if (!rangeDataAsStream.CanSeek || requiresContentMD5) + Stream writeToStream; + if (rangeDataAsStream.CanSeek) { - Stream writeToStream; - if (rangeDataAsStream.CanSeek) - { - writeToStream = Stream.Null; - } - else - { - seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); - seekableStreamCreated = true; - writeToStream = seekableStream; - } - - StreamDescriptor streamCopyState = new StreamDescriptor(); - long startPosition = seekableStream.Position; - await rangeDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken); - seekableStream.Position = startPosition; + writeToStream = Stream.Null; + } + else + { + seekableStream = new MultiBufferMemoryStream(this.ServiceClient.BufferManager); + seekableStreamCreated = true; + writeToStream = seekableStream; + } - if (requiresContentMD5) - { - contentMD5 = streamCopyState.Md5; - } + StreamDescriptor streamCopyState = new StreamDescriptor(); + long startPosition = seekableStream.Position; + await rangeDataAsStream.WriteToAsync(writeToStream, null /* copyLength */, Constants.MaxBlockSize, requiresContentMD5, tempExecutionState, streamCopyState, cancellationToken).ConfigureAwait(false); + seekableStream.Position = startPosition; - if (modifiedOptions.MaximumExecutionTime.HasValue) - { - modifiedOptions.MaximumExecutionTime -= DateTime.Now.Subtract(streamCopyStartTime); - } + if (requiresContentMD5) + { + contentMD5 = streamCopyState.Md5; } - await Executor.ExecuteAsyncNullReturn( - this.PutRangeImpl(seekableStream, startOffset, contentMD5, accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - } - finally - { - if (seekableStreamCreated) + if (modifiedOptions.MaximumExecutionTime.HasValue) { - seekableStream.Dispose(); + modifiedOptions.MaximumExecutionTime -= DateTime.Now.Subtract(streamCopyStartTime); } } - }, cancellationToken); + + await Executor.ExecuteAsyncNullReturn( + this.PutRangeImpl(seekableStream, startOffset, contentMD5, accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + } + finally + { + if (seekableStreamCreated) + { + seekableStream.Dispose(); + } + } } /// @@ -1394,11 +1362,11 @@ public virtual Task ClearRangeAsync(long startOffset, long length, AccessConditi { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ClearRangeImpl(startOffset, length, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1483,11 +1451,11 @@ public virtual Task StartCopyAsync(Uri source, AccessCondition sourceAcc { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.StartCopyImpl(source, sourceAccessCondition, destAccessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1545,11 +1513,11 @@ public virtual Task AbortCopyAsync(string copyId, AccessCondition accessConditio { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.AbortCopyImpl(copyId, accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsyncNullReturn( + this.AbortCopyImpl(copyId, accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } /// @@ -1653,7 +1621,7 @@ private RESTCommand GetFileImpl(Stream destStream, long? offset, long? getCmd.PostProcessResponse = (cmd, resp, ctx) => { HttpResponseParsers.ValidateResponseStreamMd5AndLength(validateLength, storedMD5, cmd); - return Task.FromResult(NullType.Value); + return NullType.ValueTask; }; return getCmd; @@ -1780,12 +1748,9 @@ private RESTCommand> ListRangesImpl(long? offset, long? l getCmd.PostProcessResponse = (cmd, resp, ctx) => { this.UpdateETagLMTAndLength(resp, true); - return Task.Factory.StartNew(() => - { - ListRangesResponse listRangesResponse = new ListRangesResponse(cmd.ResponseStream); - IEnumerable ranges = listRangesResponse.Ranges.ToList(); - return ranges; - }); + ListRangesResponse listRangesResponse = new ListRangesResponse(cmd.ResponseStream); + IEnumerable ranges = listRangesResponse.Ranges.ToList(); + return Task.FromResult(ranges); }; return getCmd; diff --git a/Lib/WindowsRuntime/File/CloudFileClient.cs b/Lib/WindowsRuntime/File/CloudFileClient.cs index ee4dcdd08..e2a112a71 100644 --- a/Lib/WindowsRuntime/File/CloudFileClient.cs +++ b/Lib/WindowsRuntime/File/CloudFileClient.cs @@ -105,19 +105,16 @@ public virtual Task ListSharesSegmentedAsync(string prefix, /// A to observe while waiting for a task to complete. /// A result segment of shares. [DoesServiceRequest] - public virtual Task ListSharesSegmentedAsync(string prefix, ShareListingDetails detailsIncluded, int? maxResults, FileContinuationToken currentToken, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task ListSharesSegmentedAsync(string prefix, ShareListingDetails detailsIncluded, int? maxResults, FileContinuationToken currentToken, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { - return Task.Run(async () => - { - FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this); - ResultSegment resultSegment = await Executor.ExecuteAsync( - this.ListSharesImpl(prefix, detailsIncluded, currentToken, maxResults, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); + FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this); + ResultSegment resultSegment = await Executor.ExecuteAsync( + this.ListSharesImpl(prefix, detailsIncluded, currentToken, maxResults, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); - return new ShareResultSegment(resultSegment.Results, (FileContinuationToken)resultSegment.ContinuationToken); - }, cancellationToken); + return new ShareResultSegment(resultSegment.Results, (FileContinuationToken)resultSegment.ContinuationToken); } /// @@ -155,12 +152,11 @@ public virtual Task GetServicePropertiesAsync(FileRequest FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run( - async () => await Executor.ExecuteAsync( - this.GetServicePropertiesImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServicePropertiesImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } /// @@ -200,11 +196,11 @@ public virtual Task SetServicePropertiesAsync(FileServiceProperties properties, { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(requestOptions, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.SetServicePropertiesImpl(properties, modifiedOptions), + return Executor.ExecuteAsyncNullReturn( + this.SetServicePropertiesImpl(properties, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -232,25 +228,22 @@ private RESTCommand> ListSharesImpl(string prefix, getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => + ListSharesResponse listSharesResponse = new ListSharesResponse(cmd.ResponseStream); + List sharesList = listSharesResponse.Shares.Select(item => new CloudFileShare(item.Properties, item.Metadata, item.Name, item.SnapshotTime, this)).ToList(); + FileContinuationToken continuationToken = null; + if (listSharesResponse.NextMarker != null) + { + continuationToken = new FileContinuationToken() { - ListSharesResponse listSharesResponse = new ListSharesResponse(cmd.ResponseStream); - List sharesList = listSharesResponse.Shares.Select(item => new CloudFileShare(item.Properties, item.Metadata, item.Name, item.SnapshotTime, this)).ToList(); - FileContinuationToken continuationToken = null; - if (listSharesResponse.NextMarker != null) - { - continuationToken = new FileContinuationToken() - { - NextMarker = listSharesResponse.NextMarker, - TargetLocation = cmd.CurrentResult.TargetLocation, - }; - } + NextMarker = listSharesResponse.NextMarker, + TargetLocation = cmd.CurrentResult.TargetLocation, + }; + } - return new ResultSegment(sharesList) - { - ContinuationToken = continuationToken, - }; - }); + return Task.FromResult(new ResultSegment(sharesList) + { + ContinuationToken = continuationToken, + }); }; return getCmd; @@ -269,7 +262,7 @@ private RESTCommand GetServicePropertiesImpl(FileRequestO retCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => FileHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); + return Task.FromResult(FileHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); }; requestOptions.ApplyToStorageCommand(retCmd); diff --git a/Lib/WindowsRuntime/File/CloudFileDirectory.cs b/Lib/WindowsRuntime/File/CloudFileDirectory.cs index ef2495bb6..8f1ba541f 100644 --- a/Lib/WindowsRuntime/File/CloudFileDirectory.cs +++ b/Lib/WindowsRuntime/File/CloudFileDirectory.cs @@ -67,11 +67,11 @@ public virtual Task CreateAsync(FileRequestOptions options, OperationContext ope { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async() => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateDirectoryImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -107,48 +107,45 @@ public virtual Task CreateIfNotExistsAsync(FileRequestOptions options, Ope /// true if the directory did not already exist and was created; otherwise false. /// This API requires Create or Write permissions. [DoesServiceRequest] - public virtual Task CreateIfNotExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task CreateIfNotExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => + try { - try + // Root directory always exists if the share exists. + // We cannot call this.CreateDirectoryImpl if this is the root directory, because the service will always + // return a 405 error in that case, regardless of whether or not the share exists. + if (string.IsNullOrEmpty(this.Name)) { - // Root directory always exists if the share exists. - // We cannot call this.CreateDirectoryImpl if this is the root directory, because the service will always - // return a 405 error in that case, regardless of whether or not the share exists. - if (string.IsNullOrEmpty(this.Name)) - { - // If the share does not exist, this fetch call will throw a 404, which is what we want. - await Executor.ExecuteAsync( - this.FetchAttributesImpl(null, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - return false; - } - + // If the share does not exist, this fetch call will throw a 404, which is what we want. await Executor.ExecuteAsync( - this.CreateDirectoryImpl(modifiedOptions), + this.FetchAttributesImpl(null, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken); + cancellationToken).ConfigureAwait(false); + return false; + } + + await Executor.ExecuteAsync( + this.CreateDirectoryImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); - return true; + return true; + } + catch (StorageException e) + { + if ((e.RequestInformation.ExtendedErrorInformation != null) && + (e.RequestInformation.ExtendedErrorInformation.ErrorCode == FileErrorCodeStrings.ResourceAlreadyExists)) + { + return false; } - catch (StorageException e) + else { - if ((e.RequestInformation.ExtendedErrorInformation != null) && - (e.RequestInformation.ExtendedErrorInformation.ErrorCode == FileErrorCodeStrings.ResourceAlreadyExists)) - { - return false; - } - else - { - throw; - } + throw; } - }, cancellationToken); + } } /// @@ -184,11 +181,11 @@ public virtual Task DeleteAsync(AccessCondition accessCondition, FileRequestOpti { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteDirectoryImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -223,54 +220,51 @@ public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, F /// A to observe while waiting for a task to complete. /// true if the directory already existed and was deleted; otherwise, false. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => + try { - try - { - bool exists = await Executor.ExecuteAsync( - this.ExistsImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); + bool exists = await Executor.ExecuteAsync( + this.ExistsImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); - if (!exists) - { - return false; - } + if (!exists) + { + return false; } - catch (StorageException e) + } + catch (StorageException e) + { + if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) { - if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) - { - throw; - } + throw; } + } - try - { - await Executor.ExecuteAsync( - this.DeleteDirectoryImpl(accessCondition, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); + try + { + await Executor.ExecuteAsync( + this.DeleteDirectoryImpl(accessCondition, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); - return true; + return true; + } + catch (StorageException e) + { + if (e.RequestInformation.HttpStatusCode == (int)HttpStatusCode.NotFound) + { + return false; } - catch (StorageException e) + else { - if (e.RequestInformation.HttpStatusCode == (int)HttpStatusCode.NotFound) - { - return false; - } - else - { - throw; - } + throw; } - }, cancellationToken); + } } /// @@ -306,11 +300,11 @@ public virtual Task ExistsAsync(FileRequestOptions options, OperationConte public virtual Task ExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ExistsImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -345,11 +339,11 @@ public virtual Task FetchAttributesAsync(AccessCondition accessCondition, FileRe public virtual Task FetchAttributesAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.FetchAttributesImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -427,19 +421,16 @@ public virtual Task ListFilesAndDirectoriesSegmentedAsync(int /// A to observe while waiting for a task to complete. /// A file result segment. [DoesServiceRequest] - public virtual Task ListFilesAndDirectoriesSegmentedAsync(string prefix, int? maxResults, FileContinuationToken currentToken, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task ListFilesAndDirectoriesSegmentedAsync(string prefix, int? maxResults, FileContinuationToken currentToken, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => - { - ResultSegment resultSegment = await Executor.ExecuteAsync( - this.ListFilesAndDirectoriesImpl(maxResults, modifiedOptions, currentToken, prefix), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); + ResultSegment resultSegment = await Executor.ExecuteAsync( + this.ListFilesAndDirectoriesImpl(maxResults, modifiedOptions, currentToken, prefix), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); - return new FileResultSegment(resultSegment.Results, (FileContinuationToken)resultSegment.ContinuationToken); - }, cancellationToken); + return new FileResultSegment(resultSegment.Results, (FileContinuationToken)resultSegment.ContinuationToken); } /// @@ -475,11 +466,11 @@ public virtual Task SetMetadataAsync(AccessCondition accessCondition, FileReques { this.Share.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetMetadataImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -603,24 +594,21 @@ private RESTCommand> ListFilesAndDirectoriesImpl(in getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => + ListFilesAndDirectoriesResponse listFilesResponse = new ListFilesAndDirectoriesResponse(cmd.ResponseStream); + List fileList = listFilesResponse.Files.Select(item => this.SelectListFileItem(item)).ToList(); + FileContinuationToken continuationToken = null; + if (listFilesResponse.NextMarker != null) { - ListFilesAndDirectoriesResponse listFilesResponse = new ListFilesAndDirectoriesResponse(cmd.ResponseStream); - List fileList = listFilesResponse.Files.Select(item => this.SelectListFileItem(item)).ToList(); - FileContinuationToken continuationToken = null; - if (listFilesResponse.NextMarker != null) - { - continuationToken = new FileContinuationToken() - { - NextMarker = listFilesResponse.NextMarker, - TargetLocation = cmd.CurrentResult.TargetLocation, - }; - } - - return new ResultSegment(fileList) + continuationToken = new FileContinuationToken() { - ContinuationToken = continuationToken, + NextMarker = listFilesResponse.NextMarker, + TargetLocation = cmd.CurrentResult.TargetLocation, }; + } + + return Task.FromResult(new ResultSegment(fileList) + { + ContinuationToken = continuationToken, }); }; diff --git a/Lib/WindowsRuntime/File/CloudFileShare.cs b/Lib/WindowsRuntime/File/CloudFileShare.cs index 6e1d6c19e..410a76a79 100644 --- a/Lib/WindowsRuntime/File/CloudFileShare.cs +++ b/Lib/WindowsRuntime/File/CloudFileShare.cs @@ -72,11 +72,11 @@ public virtual Task CreateAsync(FileRequestOptions options, OperationContext ope } FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateShareImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -112,7 +112,7 @@ public virtual Task CreateIfNotExistsAsync(FileRequestOptions options, Ope /// true if the share did not already exist and was created; otherwise false. /// This API requires Create or Write permissions. [DoesServiceRequest] - public virtual Task CreateIfNotExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task CreateIfNotExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { this.AssertNoSnapshot(); if (this.Properties.Quota.HasValue) @@ -123,34 +123,31 @@ public virtual Task CreateIfNotExistsAsync(FileRequestOptions options, Ope FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try - { - await this.CreateAsync(modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + await this.CreateAsync(modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == FileErrorCodeStrings.ShareAlreadyExists)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == FileErrorCodeStrings.ShareAlreadyExists)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// @@ -201,11 +198,11 @@ public virtual Task SnapshotAsync(IDictionary me public virtual Task SnapshotAsync(IDictionary metadata, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.SnapshotImpl(metadata, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -254,11 +251,11 @@ public virtual Task DeleteAsync(AccessCondition accessCondition, FileRequestOpti public virtual Task DeleteAsync(DeleteShareSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteShareImpl(deleteSnapshotsOption, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -306,55 +303,52 @@ public virtual Task DeleteIfExistsAsync(AccessCondition accessCondition, F /// A to observe while waiting for a task to complete. /// true if the share already existed and was deleted; otherwise, false. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(DeleteShareSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(DeleteShareSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try + bool exists = await this.ExistsAsync(modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + if (!exists) { - bool exists = await this.ExistsAsync(modifiedOptions, operationContext, cancellationToken); - if (!exists) - { - return false; - } + return false; } - catch (StorageException e) + } + catch (StorageException e) + { + if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) { - if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) - { - throw; - } + throw; } + } - try - { - await this.DeleteAsync(deleteSnapshotsOption, accessCondition, modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + try + { + await this.DeleteAsync(deleteSnapshotsOption, accessCondition, modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == FileErrorCodeStrings.ShareNotFound)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == FileErrorCodeStrings.ShareNotFound)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// @@ -391,11 +385,11 @@ public virtual Task ExistsAsync(FileRequestOptions options, OperationConte public virtual Task ExistsAsync(FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ExistsImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -433,11 +427,11 @@ public virtual Task FetchAttributesAsync(AccessCondition accessCondition, FileRe public virtual Task FetchAttributesAsync(AccessCondition accessCondition, FileRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.FetchAttributesImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -479,11 +473,11 @@ public virtual Task SetPermissionsAsync(FileSharePermissions permissions, Access { this.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetPermissionsImpl(permissions, accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -526,11 +520,11 @@ public virtual Task SetPropertiesAsync(AccessCondition accessCondition, FileRequ } FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetPropertiesImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -568,11 +562,11 @@ public virtual Task GetPermissionsAsync(AccessCondition ac { this.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetPermissionsImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -608,11 +602,11 @@ public virtual Task GetStatsAsync(FileRequestOptions options, Operat { this.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetStatsImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -648,11 +642,11 @@ public virtual Task SetMetadataAsync(AccessCondition accessCondition, FileReques { this.AssertNoSnapshot(); FileRequestOptions modifiedOptions = FileRequestOptions.ApplyDefaults(options, this.ServiceClient); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetMetadataImpl(accessCondition, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -841,11 +835,8 @@ private RESTCommand GetPermissionsImpl(AccessCondition acc getCmd.PostProcessResponse = (cmd, resp, ctx) => { this.UpdateETagAndLastModified(resp); - return Task.Factory.StartNew(() => - { - ShareHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, shareAcl); - return shareAcl; - }); + ShareHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, shareAcl); + return Task.FromResult(shareAcl); }; return getCmd; @@ -864,7 +855,7 @@ private RESTCommand GetStatsImpl(FileRequestOptions requestOptions) retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => ShareHttpRequestMessageFactory.GetStats(uri, serverTimeout, ctx, this.ServiceClient.GetCanonicalizer(), this.ServiceClient.Credentials); retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); - retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.Factory.StartNew(() => ShareHttpResponseParsers.ReadShareStats(cmd.ResponseStream)); + retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.FromResult(ShareHttpResponseParsers.ReadShareStats(cmd.ResponseStream)); return retCmd; } diff --git a/Lib/WindowsRuntime/File/FileReadStream.cs b/Lib/WindowsRuntime/File/FileReadStream.cs index 27a755024..ca0081def 100644 --- a/Lib/WindowsRuntime/File/FileReadStream.cs +++ b/Lib/WindowsRuntime/File/FileReadStream.cs @@ -96,7 +96,7 @@ public override int Read(byte[] buffer, int offset, int count) /// The maximum number of bytes to read. /// The token to monitor for cancellation requests. /// A task that represents the asynchronous read operation. - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { CommonUtility.AssertNotNull("buffer", buffer); CommonUtility.AssertInBounds("offset", offset, 0, buffer.Length); @@ -109,16 +109,16 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, if ((this.currentOffset == this.Length) || (count == 0)) { - return 0; + return Task.FromResult(0); } int readCount = this.ConsumeBuffer(buffer, offset, count); if (readCount > 0) { - return readCount; + return Task.FromResult(readCount); } - return await this.DispatchReadASync(buffer, offset, count); + return this.DispatchReadASync(buffer, offset, count); } /// @@ -141,7 +141,7 @@ await this.file.DownloadRangeToStreamAsync( this.GetReadSize(), null /* accessCondition */, this.options, - this.operationContext); + this.operationContext).ConfigureAwait(false); if (!this.file.Properties.ETag.Equals(this.accessCondition.IfMatchETag, StringComparison.Ordinal)) { diff --git a/Lib/WindowsRuntime/File/FileWriteStream.cs b/Lib/WindowsRuntime/File/FileWriteStream.cs index 880ef80d5..995b49d01 100644 --- a/Lib/WindowsRuntime/File/FileWriteStream.cs +++ b/Lib/WindowsRuntime/File/FileWriteStream.cs @@ -130,7 +130,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc if (bytesToWrite == maxBytesToWrite) { - await this.DispatchWriteAsync(); + await this.DispatchWriteAsync().ConfigureAwait(false); } } } @@ -160,7 +160,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken) throw this.lastException; } - await this.DispatchWriteAsync(); + await this.DispatchWriteAsync().ConfigureAwait(false); await Task.Run(() => this.noPendingWritesEvent.Wait(), cancellationToken); if (this.lastException != null) @@ -197,7 +197,7 @@ protected override void Dispose(bool disposing) /// A task that represents the asynchronous commit operation. public override async Task CommitAsync() { - await this.FlushAsync(); + await this.FlushAsync().ConfigureAwait(false); this.committed = true; try @@ -205,7 +205,7 @@ public override async Task CommitAsync() if (this.fileMD5 != null) { this.file.Properties.ContentMD5 = this.fileMD5.ComputeHash(); - await this.file.SetPropertiesAsync(this.accessCondition, this.options, this.operationContext); + await this.file.SetPropertiesAsync(this.accessCondition, this.options, this.operationContext).ConfigureAwait(false); } } catch (Exception e) @@ -240,7 +240,7 @@ private async Task DispatchWriteAsync() long offset = this.currentFileOffset; this.currentFileOffset += bufferToUpload.Length; - await this.WriteRangeAsync(bufferToUpload, offset, bufferMD5); + await this.WriteRangeAsync(bufferToUpload, offset, bufferMD5).ConfigureAwait(false); } /// @@ -253,7 +253,7 @@ private async Task DispatchWriteAsync() private async Task WriteRangeAsync(Stream rangeData, long offset, string contentMD5) { this.noPendingWritesEvent.Increment(); - await this.parallelOperationSemaphore.WaitAsync(); + await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false); Task writePagesTask = this.file.WriteRangeAsync(rangeData, offset, contentMD5, this.accessCondition, this.options, this.operationContext).ContinueWith(task => { if (task.Exception != null) diff --git a/Lib/WindowsRuntime/Queue/CloudQueue.cs b/Lib/WindowsRuntime/Queue/CloudQueue.cs index c6175962b..b91b0d682 100644 --- a/Lib/WindowsRuntime/Queue/CloudQueue.cs +++ b/Lib/WindowsRuntime/Queue/CloudQueue.cs @@ -73,11 +73,11 @@ public virtual Task CreateAsync(QueueRequestOptions options, OperationContext op QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.CreateQueueImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -113,44 +113,41 @@ public virtual Task CreateIfNotExistsAsync(QueueRequestOptions options, Op /// true if the queue did not already exist and was created; otherwise false. /// This API requires Create or Write permissions. [DoesServiceRequest] - public virtual Task CreateIfNotExistsAsync(QueueRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task CreateIfNotExistsAsync(QueueRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try + await this.CreateAsync(modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NoContent) { - await this.CreateAsync(modifiedOptions, operationContext, cancellationToken); - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NoContent) - { - return false; - } - - return true; + return false; } - catch (Exception) + + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == QueueErrorCodeStrings.QueueAlreadyExists)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == QueueErrorCodeStrings.QueueAlreadyExists)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// @@ -188,11 +185,11 @@ public virtual Task DeleteAsync(QueueRequestOptions options, OperationContext op QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteQueueImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -225,55 +222,52 @@ public virtual Task DeleteIfExistsAsync(QueueRequestOptions options, Opera /// A to observe while waiting for a task to complete. /// true if the queue already existed and was deleted; otherwise, false. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(QueueRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(QueueRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try + bool exists = await this.ExistsAsync(modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + if (!exists) { - bool exists = await this.ExistsAsync(modifiedOptions, operationContext, cancellationToken); - if (!exists) - { - return false; - } + return false; } - catch (StorageException e) + } + catch (StorageException e) + { + if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) { - if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) - { - throw; - } + throw; } + } - try - { - await this.DeleteAsync(modifiedOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + try + { + await this.DeleteAsync(modifiedOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == QueueErrorCodeStrings.QueueNotFound)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == QueueErrorCodeStrings.QueueNotFound)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } /// @@ -314,11 +308,11 @@ public virtual Task SetPermissionsAsync(QueuePermissions permissions, QueueReque QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetPermissionsImpl(permissions, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -356,11 +350,11 @@ public virtual Task GetPermissionsAsync(QueueRequestOptions op QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetPermissionsImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -411,11 +405,11 @@ private Task ExistsAsync(bool primaryOnly, QueueRequestOptions options, Op QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.ExistsImpl(modifiedOptions, primaryOnly), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -453,11 +447,11 @@ public virtual Task FetchAttributesAsync(QueueRequestOptions options, OperationC QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.FetchAttributesImpl(modifiedOptions), + return Executor.ExecuteAsyncNullReturn( + this.FetchAttributesImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -495,11 +489,11 @@ public virtual Task SetMetadataAsync(QueueRequestOptions options, OperationConte QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.SetMetadataImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -549,11 +543,11 @@ public virtual Task AddMessageAsync(CloudQueueMessage message, TimeSpan? timeToL QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.AddMessageImpl(message, timeToLive, initialVisibilityDelay, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -600,11 +594,11 @@ public virtual Task UpdateMessageAsync(CloudQueueMessage message, TimeSpan visib QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.UpdateMessageImpl(message, visibilityTimeout, updateFields, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -672,11 +666,11 @@ public virtual Task DeleteMessageAsync(string messageId, string popReceipt, Queu QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.DeleteMessageImpl(messageId, popReceipt, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -719,11 +713,11 @@ public virtual Task> GetMessagesAsync(int message QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetMessagesImpl(messageCount, visibilityTimeout, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -763,11 +757,11 @@ public virtual Task GetMessageAsync(TimeSpan? visibilityTimeo QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.GetMessageImpl(visibilityTimeout, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -808,11 +802,11 @@ public virtual Task> PeekMessagesAsync(int messag QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.PeekMessagesImpl(messageCount, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -850,11 +844,11 @@ public virtual Task PeekMessageAsync(QueueRequestOptions opti QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( + return Executor.ExecuteAsync( this.PeekMessageImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -892,11 +886,11 @@ public virtual Task ClearAsync(QueueRequestOptions options, OperationContext ope QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( + return Executor.ExecuteAsyncNullReturn( this.ClearImpl(modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } /// @@ -1083,12 +1077,9 @@ private RESTCommand GetPermissionsImpl(QueueRequestOptions opt getCmd.PostProcessResponse = (cmd, resp, ctx) => { this.GetMessageCountAndMetadataFromResponse(resp); - return Task.Factory.StartNew(() => - { - QueuePermissions queueAcl = new QueuePermissions(); - QueueHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, queueAcl); - return queueAcl; - }); + QueuePermissions queueAcl = new QueuePermissions(); + QueueHttpResponseParsers.ReadSharedAccessIdentifiers(cmd.ResponseStream, queueAcl); + return Task.FromResult(queueAcl); }; return getCmd; @@ -1134,12 +1125,9 @@ private RESTCommand AddMessageImpl(CloudQueueMessage message, TimeSpan putCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.Created, resp, null /* retVal */, cmd, ex); putCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => - { - GetMessagesResponse messageResponse = new GetMessagesResponse(cmd.ResponseStream); - CopyMessage(message, messageResponse.Messages.ToList().First()); - return NullType.Value; - }); + GetMessagesResponse messageResponse = new GetMessagesResponse(cmd.ResponseStream); + CopyMessage(message, messageResponse.Messages.ToList().First()); + return NullType.ValueTask; }; return putCmd; @@ -1227,14 +1215,11 @@ private RESTCommand> GetMessagesImpl(int messageC getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => - { - GetMessagesResponse getMessagesResponse = new GetMessagesResponse(cmd.ResponseStream); + GetMessagesResponse getMessagesResponse = new GetMessagesResponse(cmd.ResponseStream); - IEnumerable messagesList = getMessagesResponse.Messages.Select(item => SelectGetMessageResponse(item)).ToList(); + IEnumerable messagesList = getMessagesResponse.Messages.Select(item => SelectGetMessageResponse(item)).ToList(); - return messagesList; - }); + return Task.FromResult(messagesList); }; return getCmd; @@ -1257,14 +1242,11 @@ private RESTCommand> PeekMessagesImpl(int message getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => - { - GetMessagesResponse getMessagesResponse = new GetMessagesResponse(cmd.ResponseStream); + GetMessagesResponse getMessagesResponse = new GetMessagesResponse(cmd.ResponseStream); - IEnumerable messagesList = getMessagesResponse.Messages.Select(item => SelectPeekMessageResponse(item)).ToList(); + IEnumerable messagesList = getMessagesResponse.Messages.Select(item => SelectPeekMessageResponse(item)).ToList(); - return messagesList; - }); + return Task.FromResult(messagesList); }; return getCmd; @@ -1286,18 +1268,15 @@ private RESTCommand GetMessageImpl(TimeSpan? visibilityTimeou getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => + using (IEnumerator enumerator = new GetMessagesResponse(cmd.ResponseStream).Messages.GetEnumerator()) { - using (IEnumerator enumerator = new GetMessagesResponse(cmd.ResponseStream).Messages.GetEnumerator()) + if (enumerator.MoveNext()) { - if (enumerator.MoveNext()) - { - return SelectGetMessageResponse(enumerator.Current); - } + return Task.FromResult(SelectGetMessageResponse(enumerator.Current)); } + } - return null; - }); + return Null; }; return getCmd; @@ -1318,23 +1297,22 @@ private RESTCommand PeekMessageImpl(QueueRequestOptions optio getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => + using (IEnumerator enumerator = new GetMessagesResponse(cmd.ResponseStream).Messages.GetEnumerator()) { - using (IEnumerator enumerator = new GetMessagesResponse(cmd.ResponseStream).Messages.GetEnumerator()) + if (enumerator.MoveNext()) { - if (enumerator.MoveNext()) - { - return SelectPeekMessageResponse(enumerator.Current); - } + return Task.FromResult(SelectPeekMessageResponse(enumerator.Current)); } + } - return null; - }); + return Null; }; return getCmd; } + private static readonly Task Null = Task.FromResult(default(CloudQueueMessage)); + /// /// Gets the ApproximateMessageCount and metadata from response. /// diff --git a/Lib/WindowsRuntime/Queue/CloudQueueClient.cs b/Lib/WindowsRuntime/Queue/CloudQueueClient.cs index f068e8792..4bb6aa556 100644 --- a/Lib/WindowsRuntime/Queue/CloudQueueClient.cs +++ b/Lib/WindowsRuntime/Queue/CloudQueueClient.cs @@ -109,21 +109,18 @@ public virtual Task ListQueuesSegmentedAsync(string prefix, /// A to observe while waiting for a task to complete. /// A result segment of queues. [DoesServiceRequest] - public virtual Task ListQueuesSegmentedAsync(string prefix, QueueListingDetails detailsIncluded, int? maxResults, QueueContinuationToken currentToken, QueueRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task ListQueuesSegmentedAsync(string prefix, QueueListingDetails detailsIncluded, int? maxResults, QueueContinuationToken currentToken, QueueRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken) { QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => - { - ResultSegment resultSegment = await Executor.ExecuteAsync( - this.ListQueuesImpl(prefix, maxResults, detailsIncluded, modifiedOptions, currentToken), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken); - - return new QueueResultSegment(resultSegment.Results, (QueueContinuationToken)resultSegment.ContinuationToken); - }, cancellationToken); + ResultSegment resultSegment = await Executor.ExecuteAsync( + this.ListQueuesImpl(prefix, maxResults, detailsIncluded, modifiedOptions, currentToken), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken).ConfigureAwait(false); + + return new QueueResultSegment(resultSegment.Results, (QueueContinuationToken)resultSegment.ContinuationToken); } /// @@ -151,26 +148,23 @@ private RESTCommand> ListQueuesImpl(string prefix, int getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => - { - ListQueuesResponse listQueuesResponse = new ListQueuesResponse(cmd.ResponseStream); + ListQueuesResponse listQueuesResponse = new ListQueuesResponse(cmd.ResponseStream); - List queuesList = listQueuesResponse.Queues.Select(item => new CloudQueue(item.Metadata, item.Name, this)).ToList(); + List queuesList = listQueuesResponse.Queues.Select(item => new CloudQueue(item.Metadata, item.Name, this)).ToList(); - QueueContinuationToken continuationToken = null; - if (listQueuesResponse.NextMarker != null) - { - continuationToken = new QueueContinuationToken() - { - NextMarker = listQueuesResponse.NextMarker, - TargetLocation = cmd.CurrentResult.TargetLocation, - }; - } - - return new ResultSegment(queuesList) + QueueContinuationToken continuationToken = null; + if (listQueuesResponse.NextMarker != null) + { + continuationToken = new QueueContinuationToken() { - ContinuationToken = continuationToken, + NextMarker = listQueuesResponse.NextMarker, + TargetLocation = cmd.CurrentResult.TargetLocation, }; + } + + return Task.FromResult(new ResultSegment(queuesList) + { + ContinuationToken = continuationToken, }); }; @@ -214,11 +208,11 @@ public virtual Task GetServicePropertiesAsync(QueueRequestOpt QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( - this.GetServicePropertiesImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServicePropertiesImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand GetServicePropertiesImpl(QueueRequestOptions requestOptions) @@ -232,7 +226,7 @@ private RESTCommand GetServicePropertiesImpl(QueueRequestOpti HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); retCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => QueueHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); + return Task.FromResult(QueueHttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); }; requestOptions.ApplyToStorageCommand(retCmd); @@ -276,11 +270,11 @@ public virtual Task SetServicePropertiesAsync(ServiceProperties properties, Queu { QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(requestOptions, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.SetServicePropertiesImpl(properties, modifiedOptions), + return Executor.ExecuteAsyncNullReturn( + this.SetServicePropertiesImpl(properties, modifiedOptions), modifiedOptions.RetryPolicy, operationContext, - cancellationToken), cancellationToken); + cancellationToken); } private RESTCommand SetServicePropertiesImpl(ServiceProperties properties, QueueRequestOptions requestOptions) @@ -342,12 +336,11 @@ public virtual Task GetServiceStatsAsync(QueueRequestOptions optio QueueRequestOptions modifiedOptions = QueueRequestOptions.ApplyDefaults(options, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run( - async () => await Executor.ExecuteAsync( - this.GetServiceStatsImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServiceStatsImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand GetServiceStatsImpl(QueueRequestOptions requestOptions) @@ -363,7 +356,7 @@ private RESTCommand GetServiceStatsImpl(QueueRequestOptions reques retCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => QueueHttpRequestMessageFactory.GetServiceStats(uri, serverTimeout, ctx, this.GetCanonicalizer(), this.Credentials); retCmd.RetrieveResponseStream = true; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); - retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.Factory.StartNew(() => QueueHttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); + retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.FromResult(QueueHttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); return retCmd; } diff --git a/Lib/WindowsRuntime/Table/CloudTable.cs b/Lib/WindowsRuntime/Table/CloudTable.cs index 14b96b459..ad4d633b4 100644 --- a/Lib/WindowsRuntime/Table/CloudTable.cs +++ b/Lib/WindowsRuntime/Table/CloudTable.cs @@ -257,39 +257,36 @@ public virtual Task CreateIfNotExistsAsync(TableRequestOptions requestOpti /// true if table was created; otherwise, false. /// This API performs an existence check and therefore requires list permissions. [DoesServiceRequest] - public virtual Task CreateIfNotExistsAsync(TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task CreateIfNotExistsAsync(TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) { requestOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try - { - await this.CreateAsync(requestOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + await this.CreateAsync(requestOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.Conflict) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == TableErrorCodeStrings.TableAlreadyExists)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == TableErrorCodeStrings.TableAlreadyExists)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } #endregion @@ -371,54 +368,51 @@ public virtual Task DeleteIfExistsAsync(TableRequestOptions requestOptions /// true if the table already existed and was deleted; otherwise, false. /// A to observe while waiting for a task to complete. [DoesServiceRequest] - public virtual Task DeleteIfExistsAsync(TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task DeleteIfExistsAsync(TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) { requestOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => + try { - try + if (!await this.ExistsAsync(true, requestOptions, operationContext, cancellationToken).ConfigureAwait(false)) { - if (!await this.ExistsAsync(true, requestOptions, operationContext, cancellationToken)) - { - return false; - } + return false; } - catch (StorageException e) + } + catch (StorageException e) + { + if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) { - if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Forbidden) - { - throw; - } + throw; } + } - try - { - await this.DeleteAsync(requestOptions, operationContext, cancellationToken); - return true; - } - catch (Exception) + try + { + await this.DeleteAsync(requestOptions, operationContext, cancellationToken).ConfigureAwait(false); + return true; + } + catch (Exception) + { + if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) { - if (operationContext.LastResult.HttpStatusCode == (int)HttpStatusCode.NotFound) + StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; + if ((extendedInfo == null) || + (extendedInfo.ErrorCode == StorageErrorCodeStrings.ResourceNotFound)) { - StorageExtendedErrorInformation extendedInfo = operationContext.LastResult.ExtendedErrorInformation; - if ((extendedInfo == null) || - (extendedInfo.ErrorCode == StorageErrorCodeStrings.ResourceNotFound)) - { - return false; - } - else - { - throw; - } + return false; } else { throw; } } - }, cancellationToken); + else + { + throw; + } + } } #endregion @@ -467,7 +461,7 @@ public virtual Task ExistsAsync(TableRequestOptions requestOptions, Operat /// A to observe while waiting for a task to complete. /// true if the table exists. [DoesServiceRequest] - private Task ExistsAsync(bool primaryOnly, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) + private async Task ExistsAsync(bool primaryOnly, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) { requestOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); @@ -478,13 +472,10 @@ private Task ExistsAsync(bool primaryOnly, TableRequestOptions requestOpti operation.IsTableEntity = true; operation.IsPrimaryOnlyRetrieve = primaryOnly; - return Task.Run(async () => - { - TableResult res = await this.ServiceClient.ExecuteAsync(TableConstants.TableServiceTablesName, operation, requestOptions, operationContext, cancellationToken); + TableResult res = await this.ServiceClient.ExecuteAsync(TableConstants.TableServiceTablesName, operation, requestOptions, operationContext, cancellationToken).ConfigureAwait(false); - // Only other option is not found, other status codes will throw prior to this. - return res.HttpStatusCode == (int)HttpStatusCode.OK; - }, cancellationToken); + // Only other option is not found, other status codes will throw prior to this. + return res.HttpStatusCode == (int)HttpStatusCode.OK; } #endregion @@ -527,11 +518,11 @@ public virtual Task SetPermissionsAsync(TablePermissions permissions, TableReque TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.SetPermissionsImpl(permissions, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsyncNullReturn( + this.SetPermissionsImpl(permissions, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } /// @@ -596,11 +587,11 @@ public virtual Task GetPermissionsAsync(TableRequestOptions re TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(requestOptions, this.ServiceClient); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( - this.GetPermissionsImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetPermissionsImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } /// @@ -620,12 +611,9 @@ private RESTCommand GetPermissionsImpl(TableRequestOptions req getCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); getCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => - { - TablePermissions TableAcl = new TablePermissions(); - HttpResponseParsers.ReadSharedAccessIdentifiers(TableAcl.SharedAccessPolicies, new TableAccessPolicyResponse(cmd.ResponseStream)); - return TableAcl; - }); + TablePermissions TableAcl = new TablePermissions(); + HttpResponseParsers.ReadSharedAccessIdentifiers(TableAcl.SharedAccessPolicies, new TableAccessPolicyResponse(cmd.ResponseStream)); + return Task.FromResult(TableAcl); }; return getCmd; diff --git a/Lib/WindowsRuntime/Table/CloudTableClient.cs b/Lib/WindowsRuntime/Table/CloudTableClient.cs index 105535a1d..9175888d1 100644 --- a/Lib/WindowsRuntime/Table/CloudTableClient.cs +++ b/Lib/WindowsRuntime/Table/CloudTableClient.cs @@ -172,24 +172,21 @@ public virtual Task ListTablesSegmentedAsync(string prefix, /// A to observe while waiting for a task to complete. /// The result segment containing the collection of tables. [DoesServiceRequest] - public virtual Task ListTablesSegmentedAsync(string prefix, int? maxResults, TableContinuationToken currentToken, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) + public virtual async Task ListTablesSegmentedAsync(string prefix, int? maxResults, TableContinuationToken currentToken, TableRequestOptions requestOptions, OperationContext operationContext, CancellationToken cancellationToken) { requestOptions = TableRequestOptions.ApplyDefaults(requestOptions, this); operationContext = operationContext ?? new OperationContext(); TableQuery query = this.GenerateListTablesQuery(prefix, maxResults); - return Task.Run(async () => - { - TableQuerySegment seg = await this.ExecuteQuerySegmentedAsync(TableConstants.TableServiceTablesName, query, currentToken, requestOptions, operationContext, cancellationToken); - TableResultSegment retSegment = new TableResultSegment(seg.Results.Select(tbl => new CloudTable(tbl.Properties[TableConstants.TableName].StringValue, this)).ToList()); - retSegment.ContinuationToken = seg.ContinuationToken; - return retSegment; - }, cancellationToken); + TableQuerySegment seg = await this.ExecuteQuerySegmentedAsync(TableConstants.TableServiceTablesName, query, currentToken, requestOptions, operationContext, cancellationToken).ConfigureAwait(false); + TableResultSegment retSegment = new TableResultSegment(seg.Results.Select(tbl => new CloudTable(tbl.Properties[TableConstants.TableName].StringValue, this)).ToList()); + retSegment.ContinuationToken = seg.ContinuationToken; + return retSegment; } -#endregion + #endregion -#region Analytics + #region Analytics /// /// Gets the properties of the table service. /// @@ -225,11 +222,11 @@ public virtual Task GetServicePropertiesAsync(TableRequestOpt TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(requestOptions, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsync( - this.GetServicePropertiesImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServicePropertiesImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand GetServicePropertiesImpl(TableRequestOptions requestOptions) @@ -245,7 +242,7 @@ private RESTCommand GetServicePropertiesImpl(TableRequestOpti retCmd.PostProcessResponse = (cmd, resp, ctx) => { - return Task.Factory.StartNew(() => HttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); + return Task.FromResult(HttpResponseParsers.ReadServiceProperties(cmd.ResponseStream)); }; requestOptions.ApplyToStorageCommand(retCmd); @@ -289,11 +286,11 @@ public virtual Task SetServicePropertiesAsync(ServiceProperties properties, Tabl { TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(requestOptions, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run(async () => await Executor.ExecuteAsyncNullReturn( - this.SetServicePropertiesImpl(properties, modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsyncNullReturn( + this.SetServicePropertiesImpl(properties, modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand SetServicePropertiesImpl(ServiceProperties properties, TableRequestOptions requestOptions) @@ -356,12 +353,11 @@ public virtual Task GetServiceStatsAsync(TableRequestOptions optio TableRequestOptions modifiedOptions = TableRequestOptions.ApplyDefaults(options, this); operationContext = operationContext ?? new OperationContext(); - return Task.Run( - async () => await Executor.ExecuteAsync( - this.GetServiceStatsImpl(modifiedOptions), - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + this.GetServiceStatsImpl(modifiedOptions), + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } @@ -379,7 +375,7 @@ private RESTCommand GetServiceStatsImpl(TableRequestOptions reques retCmd.RetrieveResponseStream = true; retCmd.ParseError = ODataErrorHelper.ReadFromStreamUsingODataLib; retCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp, null /* retVal */, cmd, ex); - retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.Factory.StartNew(() => HttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); + retCmd.PostProcessResponse = (cmd, resp, ctx) => Task.FromResult(HttpResponseParsers.ReadServiceStats(cmd.ResponseStream)); return retCmd; } #endregion diff --git a/Lib/WindowsRuntime/Table/Protocol/HttpResponseAdapterMessage.cs b/Lib/WindowsRuntime/Table/Protocol/HttpResponseAdapterMessage.cs index 246ae5dc8..72cf33429 100644 --- a/Lib/WindowsRuntime/Table/Protocol/HttpResponseAdapterMessage.cs +++ b/Lib/WindowsRuntime/Table/Protocol/HttpResponseAdapterMessage.cs @@ -28,7 +28,7 @@ namespace Microsoft.WindowsAzure.Storage.Table.Protocol internal class HttpResponseAdapterMessage : IODataResponseMessageAsync { private HttpResponseMessage resp = null; - private Stream str = null; + private Task strAsCachedTask = null; private string responseContentType = null; public HttpResponseAdapterMessage(HttpResponseMessage resp, Stream str) @@ -39,13 +39,13 @@ public HttpResponseAdapterMessage(HttpResponseMessage resp, Stream str) public HttpResponseAdapterMessage(HttpResponseMessage resp, Stream str, string responseContentType) { this.resp = resp; - this.str = str; + this.strAsCachedTask = Task.FromResult(str); this.responseContentType = responseContentType; } public Task GetStreamAsync() { - return Task.Factory.StartNew(() => this.str); + return strAsCachedTask; } public string GetHeader(string headerName) @@ -75,7 +75,7 @@ public string GetHeader(string headerName) public Stream GetStream() { - return this.str; + return this.strAsCachedTask.Result; // safe since completed task and avoids additional field for stream } public IEnumerable> Headers diff --git a/Lib/WindowsRuntime/Table/TableBatchOperation.cs b/Lib/WindowsRuntime/Table/TableBatchOperation.cs index 027c52f86..f8d6b5170 100644 --- a/Lib/WindowsRuntime/Table/TableBatchOperation.cs +++ b/Lib/WindowsRuntime/Table/TableBatchOperation.cs @@ -56,11 +56,11 @@ internal Task> ExecuteAsync(CloudTableClient client, string t RESTCommand> cmdToExecute = BatchImpl(this, client, tableName, modifiedOptions); - return Task.Run(async () => await Executor.ExecuteAsync( - cmdToExecute, - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + cmdToExecute, + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private static RESTCommand> BatchImpl(TableBatchOperation batch, CloudTableClient client, string tableName, TableRequestOptions requestOptions) diff --git a/Lib/WindowsRuntime/Table/TableOperation.cs b/Lib/WindowsRuntime/Table/TableOperation.cs index dab52ade2..42de2f7cf 100644 --- a/Lib/WindowsRuntime/Table/TableOperation.cs +++ b/Lib/WindowsRuntime/Table/TableOperation.cs @@ -95,11 +95,11 @@ internal Task ExecuteAsync(CloudTableClient client, string tableNam throw new NotSupportedException(); } - return Task.Run(() => Executor.ExecuteAsync( - cmdToExecute, - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + cmdToExecute, + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private static RESTCommand InsertImpl(TableOperation operation, CloudTableClient client, string tableName, TableRequestOptions requestOptions) @@ -176,17 +176,16 @@ private static RESTCommand RetrieveImpl(TableOperation operation, C retrieveCmd.ParseError = ODataErrorHelper.ReadFromStreamUsingODataLib; retrieveCmd.BuildRequest = (cmd, uri, builder, cnt, serverTimeout, ctx) => TableOperationHttpRequestMessageFactory.BuildRequestForTableOperation(cmd, uri, builder, serverTimeout, operation, client, cnt, ctx, requestOptions.PayloadFormat.Value, client.GetCanonicalizer(), client.Credentials); retrieveCmd.PreProcessResponse = (cmd, resp, ex, ctx) => TableOperationHttpResponseParsers.TableOperationPreProcess(result, operation, resp, ex, cmd, ctx); - retrieveCmd.PostProcessResponse = (cmd, resp, ctx) => - Task.Run(async () => + retrieveCmd.PostProcessResponse = async (cmd, resp, ctx) => + { + if (resp.StatusCode == HttpStatusCode.NotFound) { - if (resp.StatusCode == HttpStatusCode.NotFound) - { - return result; - } - - result = await TableOperationHttpResponseParsers.TableOperationPostProcess(result, operation, cmd, resp, ctx, requestOptions, client.AccountName); return result; - }); + } + + result = await TableOperationHttpResponseParsers.TableOperationPostProcess(result, operation, cmd, resp, ctx, requestOptions, client.AccountName).ConfigureAwait(false); + return result; + }; return retrieveCmd; } diff --git a/Lib/WindowsRuntime/Table/TableQuery.cs b/Lib/WindowsRuntime/Table/TableQuery.cs index 0717facf3..3e20c4033 100644 --- a/Lib/WindowsRuntime/Table/TableQuery.cs +++ b/Lib/WindowsRuntime/Table/TableQuery.cs @@ -71,11 +71,11 @@ internal Task ExecuteQuerySegmentedAsync(TableContinuationTok RESTCommand cmdToExecute = QueryImpl(this, continuationToken, client, tableName, EntityUtilities.ResolveEntityByType, modifiedOptions); - return Task.Run(async () => await Executor.ExecuteAsync( - cmdToExecute, - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + cmdToExecute, + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private static RESTCommand QueryImpl(TableQuery query, TableContinuationToken token, CloudTableClient client, string tableName, EntityResolver resolver, TableRequestOptions requestOptions) @@ -99,7 +99,7 @@ private static RESTCommand QueryImpl(TableQuery query, TableC queryCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp.StatusCode, null /* retVal */, cmd, ex); queryCmd.PostProcessResponse = async (cmd, resp, ctx) => { - ResultSegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGeneric(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName); + ResultSegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGeneric(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName).ConfigureAwait(false); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation; @@ -119,11 +119,11 @@ internal Task> ExecuteQuerySegmentedAsync(Ta RESTCommand> cmdToExecute = this.QueryImpl(continuationToken, client, tableName, resolver, modifiedOptions); - return Task.Run(async () => await Executor.ExecuteAsync( - cmdToExecute, - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + cmdToExecute, + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private RESTCommand> QueryImpl(TableContinuationToken token, CloudTableClient client, string tableName, EntityResolver resolver, TableRequestOptions requestOptions) @@ -147,7 +147,7 @@ private RESTCommand> QueryImpl(Table queryCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp.StatusCode, null /* retVal */, cmd, ex); queryCmd.PostProcessResponse = async (cmd, resp, ctx) => { - ResultSegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGeneric(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName); + ResultSegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGeneric(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName).ConfigureAwait(false); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation; diff --git a/Lib/WindowsRuntime/Table/TableQueryGeneric.cs b/Lib/WindowsRuntime/Table/TableQueryGeneric.cs index e781ed914..e85c39a8e 100644 --- a/Lib/WindowsRuntime/Table/TableQueryGeneric.cs +++ b/Lib/WindowsRuntime/Table/TableQueryGeneric.cs @@ -76,11 +76,11 @@ internal Task> ExecuteQuerySegmentedAsync(TableConti RESTCommand> cmdToExecute = QueryImpl(this, token, client, tableName, EntityUtilities.ResolveEntityByType, modifiedOptions); - return Task.Run(async () => await Executor.ExecuteAsync( - cmdToExecute, - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + cmdToExecute, + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } internal IEnumerable Execute(CloudTableClient client, string tableName, EntityResolver resolver, TableRequestOptions requestOptions, OperationContext operationContext) @@ -119,11 +119,11 @@ internal Task> ExecuteQuerySegmentedAsync(Ta RESTCommand> cmdToExecute = QueryImpl(this, token, client, tableName, resolver, modifiedOptions); - return Task.Run(() => Executor.ExecuteAsync( - cmdToExecute, - modifiedOptions.RetryPolicy, - operationContext, - cancellationToken), cancellationToken); + return Executor.ExecuteAsync( + cmdToExecute, + modifiedOptions.RetryPolicy, + operationContext, + cancellationToken); } private static RESTCommand> QueryImpl(TableQuery query, TableContinuationToken token, CloudTableClient client, string tableName, EntityResolver resolver, TableRequestOptions requestOptions) where T : ITableEntity, new() @@ -147,7 +147,7 @@ internal Task> ExecuteQuerySegmentedAsync(Ta queryCmd.PreProcessResponse = (cmd, resp, ex, ctx) => HttpResponseParsers.ProcessExpectedStatusCodeNoException(HttpStatusCode.OK, resp.StatusCode, null /* retVal */, cmd, ex); queryCmd.PostProcessResponse = async (cmd, resp, ctx) => { - ResultSegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGeneric(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName); + ResultSegment resSeg = await TableOperationHttpResponseParsers.TableQueryPostProcessGeneric(cmd.ResponseStream, resolver.Invoke, resp, requestOptions, ctx, client.AccountName).ConfigureAwait(false); if (resSeg.ContinuationToken != null) { resSeg.ContinuationToken.TargetLocation = cmd.CurrentResult.TargetLocation;