/// <summary> /// Initiates an asynchronous request/response transmission with a specific timeout. /// </summary> /// <param name="message">The request message.</param> /// <param name="timeout">The maximum time to wait for a response.</param> /// <param name="callback">The <see cref="AsyncCallback" /> delegate to be called when the operation completes (or <c>null</c>).</param> /// <param name="state">The application specific state (or <c>null</c>).</param> /// <returns>The <see cref="IAsyncResult" /> instance to be used to track the status of the operation.</returns> /// <remarks> /// <note> /// All successful calls to <see cref="BeginRequest(Message,TimeSpan,AsyncCallback,object)" /> must /// eventually be followed by a call to <see cref="EndRequest" />. /// </note> /// </remarks> public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state) { using (TimedLock.Lock(this)) { ThrowIfDisposedOrNotOpen(); ServiceModelHelper.ValidateTimeout(timeout); try { using (MemoryStream ms = new MemoryStream(payloadEstimator.EstimateNextBufferSize())) { WcfEnvelopeMsg requestMsg = new WcfEnvelopeMsg(); encoder.WriteMessage(message, ms); payloadEstimator.LastPayloadSize((int)ms.Length); requestMsg.Payload = new ArraySegment <byte>(ms.GetBuffer(), 0, (int)ms.Length); return(ChannelHost.Router.BeginQuery(ep, requestMsg, callback, state)); } } catch (Exception e) { throw ServiceModelHelper.GetCommunicationException(e); } } }
/// <summary> /// Intitiates an asynchronous operation to send a reply to the context request. /// </summary> /// <param name="context">The <see cref="LillTekRequestContext" /> context.</param> /// <param name="message">The reply <see cref="Message" />.</param> /// <param name="callback">The <see cref="AsyncCallback" /> delegate to be called when the operation completes (or <c>null</c>).</param> /// <param name="state">Application defined state (or <c>null</c>).</param> /// <returns>The <see cref="IAsyncResult" /> to be used to track the status of the operation.</returns> /// <remarks> /// <note> /// Every successful call to <see cref="BeginReply(LillTekRequestContext,Message,AsyncCallback,object)" /> must eventually be followed by /// a call to <see cref="EndReply" />. /// </note> /// </remarks> public IAsyncResult BeginReply(LillTekRequestContext context, Message message, AsyncCallback callback, object state) { AsyncResult arReply; // This operation is inherently asynchronous at the LillTek Messaging level // so we'll complete the operation immediately. using (MemoryStream ms = new MemoryStream(payloadEstimator.EstimateNextBufferSize())) { WcfEnvelopeMsg replyMsg = new WcfEnvelopeMsg(); encoder.WriteMessage(message, ms); payloadEstimator.LastPayloadSize((int)ms.Length); replyMsg.Payload = new ArraySegment <byte>(ms.GetBuffer(), 0, (int)ms.Length); using (TimedLock.Lock(this)) { if (pendingRequests.ContainsKey(context.MsgRequestContext.SessionID)) { pendingRequests.Remove(context.MsgRequestContext.SessionID); } context.MsgRequestContext.Reply(replyMsg); } } arReply = new AsyncResult(null, callback, state); arReply.Started(ServiceModelHelper.AsyncTrace); arReply.Notify(); return(arReply); }
/// <summary> /// Synchronously sends a message on the output channel. /// </summary> /// <param name="message">The <see cref="Message" />.</param> /// <remarks> /// <note> /// This method does not guarantee delivery of the message. /// Messages can be silently dropped for reasons including lack of buffer /// space, network congestion, unavailable remote endpoint, etc. /// </note> /// </remarks> public void Send(Message message) { try { using (MemoryStream ms = new MemoryStream(payloadEstimator.EstimateNextBufferSize())) { WcfEnvelopeMsg envelopeMsg = new WcfEnvelopeMsg(); encoder.WriteMessage(message, ms); payloadEstimator.LastPayloadSize((int)ms.Length); envelopeMsg.Payload = new ArraySegment <byte>(ms.GetBuffer(), 0, (int)ms.Length); ChannelHost.Router.SendTo(ep, envelopeMsg); } } catch (Exception e) { throw ServiceModelHelper.GetCommunicationException(e); } }