/// <summary> /// Ends the asynchronous query request. /// </summary> /// <typeparam name="TElement">Element type of the result.</typeparam> /// <param name="source">Source object of async request.</param> /// <param name="method">async method name.</param> /// <param name="asyncResult">The asyncResult being ended.</param> /// <returns>Data service response.</returns> internal static QueryResult EndExecuteQuery <TElement>(object source, string method, IAsyncResult asyncResult) { QueryResult response = null; try { response = BaseAsyncResult.EndExecute <QueryResult>(source, method, asyncResult); } catch (InvalidOperationException ex) { response = asyncResult as QueryResult; Debug.Assert(response != null, "response != null, BaseAsyncResult.EndExecute() would have thrown a different exception otherwise."); QueryOperationResponse operationResponse = response.GetResponse <TElement>(MaterializeAtom.EmptyResults); if (operationResponse != null) { operationResponse.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse); } throw; } return(response); }
/// <summary> /// Make async calls to read the response stream. /// </summary> /// <param name="asyncStateBag">the state containing the information about the asynchronous operation.</param> private void ReadResponseStream(AsyncStateBag asyncStateBag) { Debug.Assert(asyncStateBag != null, "asyncStateBag != null"); PerRequest pereq = asyncStateBag.PerRequest; IAsyncResult asyncResult = null; byte[] buffer = this.asyncStreamCopyBuffer; Stream httpResponseStream = pereq.ResponseStream; do { int bufferOffset = 0; int bufferLength = buffer.Length; this.usingBuffer = true; #if WINRT asyncResult = BaseAsyncResult.InvokeTask(httpResponseStream.ReadAsync, buffer, bufferOffset, bufferLength, this.AsyncEndRead, asyncStateBag); #else asyncResult = BaseAsyncResult.InvokeAsync(httpResponseStream.BeginRead, buffer, bufferOffset, bufferLength, this.AsyncEndRead, asyncStateBag); #endif pereq.SetRequestCompletedSynchronously(asyncResult.CompletedSynchronously); this.SetCompletedSynchronously(asyncResult.CompletedSynchronously); // BeginRead }while (asyncResult.CompletedSynchronously && !pereq.RequestCompleted && !this.IsCompletedInternally && httpResponseStream.CanRead); Debug.Assert((!this.CompletedSynchronously && !pereq.RequestCompletedSynchronously) || this.IsCompletedInternally || pereq.RequestCompleted, "AsyncEndGetResponse !IsCompleted"); }
internal void BeginExecuteQuery() { IAsyncResult asyncResult = null; PerRequest pereq = new PerRequest(); AsyncStateBag asyncStateBag = new AsyncStateBag(pereq); pereq.Request = this.Request; this.perRequest = pereq; try { if (this.requestContentStream != null && this.requestContentStream.Stream != null) { if (this.requestContentStream.IsKnownMemoryStream) { this.Request.SetContentLengthHeader(); } this.perRequest.RequestContentStream = this.requestContentStream; asyncResult = BaseAsyncResult.InvokeAsync(this.Request.BeginGetRequestStream, this.AsyncEndGetRequestStream, asyncStateBag); } else { asyncResult = BaseAsyncResult.InvokeAsync(this.Request.BeginGetResponse, this.AsyncEndGetResponse, asyncStateBag); } // TODO: 298920: Async execute methods for query (QueryResult.cs), should not need to maintain "CompletedSynchronously" information in two state variables. pereq.SetRequestCompletedSynchronously(asyncResult.CompletedSynchronously); this.SetCompletedSynchronously(asyncResult.CompletedSynchronously); } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.HandleCompleted(pereq); } Debug.Assert((!this.CompletedSynchronously && !pereq.RequestCompletedSynchronously) || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted"); }
internal void Begin() { try { IAsyncResult asyncResult = BaseAsyncResult.InvokeAsync(this.requestMessage.BeginGetResponse, this.AsyncEndGetResponse, null); this.SetCompletedSynchronously(asyncResult.CompletedSynchronously); } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.HandleCompleted(); } Debug.Assert(!this.CompletedSynchronously || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted"); }
/// <summary>initial the async batch save changeset</summary> internal void BatchBeginRequest() { PerRequest pereq = null; try { ODataRequestMessageWrapper batchRequestMessage = this.GenerateBatchRequest(); this.Abortable = batchRequestMessage; if (batchRequestMessage != null) { batchRequestMessage.SetContentLengthHeader(); this.perRequest = pereq = new PerRequest(); pereq.Request = batchRequestMessage; pereq.RequestContentStream = batchRequestMessage.CachedRequestStream; AsyncStateBag asyncStateBag = new AsyncStateBag(pereq); this.responseStream = new MemoryStream(); IAsyncResult asyncResult = BaseAsyncResult.InvokeAsync(batchRequestMessage.BeginGetRequestStream, this.AsyncEndGetRequestStream, asyncStateBag); pereq.SetRequestCompletedSynchronously(asyncResult.CompletedSynchronously); } else { Debug.Assert(this.CompletedSynchronously, "completedSynchronously"); Debug.Assert(this.IsCompletedInternally, "completed"); } } catch (Exception e) { this.HandleFailure(pereq, e); throw; // to user on BeginSaveChangeSet, will still invoke Callback } finally { this.HandleCompleted(pereq); // will invoke user callback } Debug.Assert((this.CompletedSynchronously && this.IsCompleted) || !this.CompletedSynchronously, "sync without complete"); }
/// <summary>Set the AsyncWait and invoke the user callback.</summary> /// <param name="pereq">the request object</param> /// <remarks>This method is not implemented for this class.</remarks> protected override void HandleCompleted(BaseAsyncResult.PerRequest pereq) { Debug.Assert(false, "This method should never be called from GetReadStreamResult."); Error.ThrowInternalError(InternalError.InvalidHandleCompleted); }
internal void BeginCreateNextChange() { Debug.Assert(!this.IsCompletedInternally, "why being called if already completed?"); // create the memory stream required to cache the responses as we read async from the underlying http web response this.inMemoryResponseStream = new MemoryStream(); // SaveCallback can't chain synchronously completed responses, caller will loop the to next change PerRequest pereq = null; IAsyncResult asyncResult = null; do { IODataResponseMessage responseMsg = null; ODataRequestMessageWrapper requestMessage = null; try { if (this.perRequest != null) { this.SetCompleted(); Error.ThrowInternalError(InternalError.InvalidBeginNextChange); } requestMessage = this.CreateNextRequest(); // Keeping the old behavior (V1/V2) where the abortable was set to null, // if CreateNextRequest returned null. if (requestMessage == null) { this.Abortable = null; } if ((requestMessage != null) || (this.entryIndex < this.ChangedEntries.Count)) { if (this.ChangedEntries[this.entryIndex].ContentGeneratedForSave) { Debug.Assert(this.ChangedEntries[this.entryIndex] is LinkDescriptor, "only expected RelatedEnd to presave"); Debug.Assert( this.ChangedEntries[this.entryIndex].State == EntityStates.Added || this.ChangedEntries[this.entryIndex].State == EntityStates.Modified, "only expected added to presave"); continue; } this.Abortable = requestMessage; ContentStream contentStream = this.CreateNonBatchChangeData(this.entryIndex, requestMessage); this.perRequest = pereq = new PerRequest(); pereq.Request = requestMessage; AsyncStateBag asyncStateBag = new AsyncStateBag(pereq); if (contentStream == null || contentStream.Stream == null) { asyncResult = BaseAsyncResult.InvokeAsync(requestMessage.BeginGetResponse, this.AsyncEndGetResponse, asyncStateBag); } else { if (contentStream.IsKnownMemoryStream) { requestMessage.SetContentLengthHeader(); } pereq.RequestContentStream = contentStream; asyncResult = BaseAsyncResult.InvokeAsync(requestMessage.BeginGetRequestStream, this.AsyncEndGetRequestStream, asyncStateBag); } pereq.SetRequestCompletedSynchronously(asyncResult.CompletedSynchronously); this.SetCompletedSynchronously(pereq.RequestCompletedSynchronously); } else { this.SetCompleted(); if (this.CompletedSynchronously) { this.HandleCompleted(pereq); } } } catch (InvalidOperationException e) { e = WebUtil.GetHttpWebResponse(e, ref responseMsg); this.HandleOperationException(e, responseMsg); this.HandleCompleted(pereq); } finally { WebUtil.DisposeMessage(responseMsg); } // If the current request is completed synchronously, we need to call FinishCurrentChange() to process the response payload. // FinishCurrentChange() will not call BeginCreateNextChange() when the request is synchronous. // If the current request is completed asynchronously, an async thread will call FinishCurrentChange() to process the response payload. // FinishCurrentchange() will then call BeginCreateNextChange() from the async thread and we need to exit this loop. // If requestMessage = this.CreateNextRequest() returns null, we would have called this.SetCompleted() above and this.IsCompletedInternally // would be true. This means we are done processing all changed entries and we should not call this.FinishCurrentChange(). if (pereq != null && pereq.RequestCompleted && pereq.RequestCompletedSynchronously && !this.IsCompletedInternally) { Debug.Assert(requestMessage != null, "httpWebRequest != null"); this.FinishCurrentChange(pereq); } // In the condition for the do-while loop we must test for pereq.RequestCompletedSynchronously and not asyncResult.CompletedSynchronously. // pereq.RequestCompletedSynchronously is true only if all async calls completed synchronously. If we don't exit this loop when // pereq.RequestCompletedSynchronously is false, the current thread and an async thread will both re-enter BeginCreateNextChange() // and we will fail. We can only process one request at a given time. }while (((pereq == null) || (pereq.RequestCompleted && pereq.RequestCompletedSynchronously)) && !this.IsCompletedInternally); Debug.Assert((this.CompletedSynchronously && this.IsCompleted) || !this.CompletedSynchronously, "sync without complete"); Debug.Assert(this.entryIndex < this.ChangedEntries.Count || this.ChangedEntries.All(o => o.ContentGeneratedForSave), "didn't generate content for all entities/links"); }
protected override void FinishCurrentChange(BaseAsyncResult.PerRequest pereq) { base.FinishCurrentChange(pereq); this.ResponseStream.Position = 0L; base.perRequest = null; base.SetCompleted(); }
protected override void FinishCurrentChange(BaseAsyncResult.PerRequest pereq) { base.FinishCurrentChange(pereq); if (this.ResponseStream.Position != 0L) { this.ResponseStream.Position = 0L; this.HandleOperationResponseData(this.httpWebResponse, this.ResponseStream); } else { this.HandleOperationResponseData(this.httpWebResponse, null); } pereq.Dispose(); base.perRequest = null; if (!pereq.RequestCompletedSynchronously && !base.IsCompletedInternally) { this.BeginCreateNextChange(); } }
internal AsyncReadState(BaseAsyncResult.PerRequest pereq) { this.Pereq = pereq; this.totalByteCopied = 0; }
protected override void HandleCompleted(BaseAsyncResult.PerRequest pereq) { if (pereq != null) { base.SetCompletedSynchronously(pereq.RequestCompletedSynchronously); if (pereq.RequestCompleted) { Interlocked.CompareExchange<BaseAsyncResult.PerRequest>(ref this.perRequest, null, pereq); if (this.IsBatch) { Interlocked.CompareExchange<HttpWebResponse>(ref this.batchResponse, pereq.HttpWebResponse, null); pereq.HttpWebResponse = null; } pereq.Dispose(); } } base.HandleCompleted(); }
protected override void HandleCompleted(BaseAsyncResult.PerRequest pereq) { Error.ThrowInternalError(InternalError.InvalidHandleCompleted); }