static bool HandleEndResumeBookmark(IAsyncResult result) { WorkflowOperationContext thisPtr = (WorkflowOperationContext)result.AsyncState; bool completed = false; bool shouldAbandon = true; try { BookmarkResumptionResult resumptionResult = thisPtr.workflowInstance.EndResumeProtocolBookmark(result); if (resumptionResult != BookmarkResumptionResult.Success) { // Raise UnkownMessageReceivedEvent when we fail to resume bookmark thisPtr.OperationContext.Host.RaiseUnknownMessageReceived(thisPtr.OperationContext.IncomingMessage); // Only delay-retry this operation once (and only if retries are supported). Future calls will ensure the bookmark is set. if (thisPtr.workflowInstance.BufferedReceiveManager != null) { bool bufferSuccess = thisPtr.workflowInstance.BufferedReceiveManager.BufferReceive( thisPtr.OperationContext, thisPtr.receiveContext, thisPtr.bookmark.Name, BufferedReceiveState.WaitingOnBookmark, false); if (bufferSuccess) { if (TD.BufferOutOfOrderMessageNoBookmarkIsEnabled()) { TD.BufferOutOfOrderMessageNoBookmark(thisPtr.eventTraceActivity, thisPtr.workflowInstance.Id.ToString(), thisPtr.bookmark.Name); } shouldAbandon = false; } } // The throw exception is intentional whether or not BufferedReceiveManager is set. // This is to allow exception to bubble up the stack to WCF to cleanup various state (like Transaction). // This is queue scenario and as far as the client is concerned, the client will not see any exception. throw FxTrace.Exception.AsError(new FaultException(OperationExecutionFault.CreateOperationNotAvailableFault(thisPtr.workflowInstance.Id, thisPtr.bookmark.Name))); } lock (thisPtr.thisLock) { if (thisPtr.CurrentState == State.ResultReceived) { thisPtr.CurrentState = State.Completed; if (thisPtr.pendingException != null) { throw FxTrace.Exception.AsError(thisPtr.pendingException); } completed = true; } else { thisPtr.CurrentState = State.WaitForResult; completed = false; } // we are not really completed until the ReceiveContext finishes its work if (completed) { completed = thisPtr.ProcessReceiveContext(); } shouldAbandon = false; } } finally { if (shouldAbandon) { BufferedReceiveManager.AbandonReceiveContext(thisPtr.receiveContext); } thisPtr.RemovePendingOperation(); } return(completed); }