ReplyChannel.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System.Collections.Generic;
  7. using System.Runtime;
  8. using System.ServiceModel;
  9. class ReplyChannel : InputQueueChannel<RequestContext>, IReplyChannel
  10. {
  11. EndpointAddress localAddress;
  12. public ReplyChannel(ChannelManagerBase channelManager, EndpointAddress localAddress)
  13. : base(channelManager)
  14. {
  15. this.localAddress = localAddress;
  16. }
  17. public EndpointAddress LocalAddress
  18. {
  19. get { return localAddress; }
  20. }
  21. public override T GetProperty<T>()
  22. {
  23. if (typeof(T) == typeof(IReplyChannel))
  24. {
  25. return (T)(object)this;
  26. }
  27. T baseProperty = base.GetProperty<T>();
  28. if (baseProperty != null)
  29. {
  30. return baseProperty;
  31. }
  32. return default(T);
  33. }
  34. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  35. {
  36. return new CompletedAsyncResult(callback, state);
  37. }
  38. protected override void OnEndOpen(IAsyncResult result)
  39. {
  40. CompletedAsyncResult.End(result);
  41. }
  42. protected override void OnOpen(TimeSpan timeout)
  43. {
  44. }
  45. #region static Helpers to convert TryReceiveRequest to ReceiveRequest
  46. internal static RequestContext HelpReceiveRequest(IReplyChannel channel, TimeSpan timeout)
  47. {
  48. RequestContext requestContext;
  49. if (channel.TryReceiveRequest(timeout, out requestContext))
  50. {
  51. return requestContext;
  52. }
  53. else
  54. {
  55. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  56. ReplyChannel.CreateReceiveRequestTimedOutException(channel, timeout));
  57. }
  58. }
  59. internal static IAsyncResult HelpBeginReceiveRequest(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state)
  60. {
  61. return new HelpReceiveRequestAsyncResult(channel, timeout, callback, state);
  62. }
  63. internal static RequestContext HelpEndReceiveRequest(IAsyncResult result)
  64. {
  65. return HelpReceiveRequestAsyncResult.End(result);
  66. }
  67. class HelpReceiveRequestAsyncResult : AsyncResult
  68. {
  69. IReplyChannel channel;
  70. TimeSpan timeout;
  71. static AsyncCallback onReceiveRequest = Fx.ThunkCallback(new AsyncCallback(OnReceiveRequest));
  72. RequestContext requestContext;
  73. public HelpReceiveRequestAsyncResult(IReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state)
  74. : base(callback, state)
  75. {
  76. this.channel = channel;
  77. this.timeout = timeout;
  78. IAsyncResult result = channel.BeginTryReceiveRequest(timeout, onReceiveRequest, this);
  79. if (!result.CompletedSynchronously)
  80. {
  81. return;
  82. }
  83. HandleReceiveRequestComplete(result);
  84. base.Complete(true);
  85. }
  86. public static RequestContext End(IAsyncResult result)
  87. {
  88. HelpReceiveRequestAsyncResult thisPtr = AsyncResult.End<HelpReceiveRequestAsyncResult>(result);
  89. return thisPtr.requestContext;
  90. }
  91. void HandleReceiveRequestComplete(IAsyncResult result)
  92. {
  93. if (!this.channel.EndTryReceiveRequest(result, out this.requestContext))
  94. {
  95. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  96. ReplyChannel.CreateReceiveRequestTimedOutException(this.channel, this.timeout));
  97. }
  98. }
  99. static void OnReceiveRequest(IAsyncResult result)
  100. {
  101. if (result.CompletedSynchronously)
  102. {
  103. return;
  104. }
  105. HelpReceiveRequestAsyncResult thisPtr = (HelpReceiveRequestAsyncResult)result.AsyncState;
  106. Exception completionException = null;
  107. try
  108. {
  109. thisPtr.HandleReceiveRequestComplete(result);
  110. }
  111. #pragma warning suppress 56500 // [....], transferring exception to another thread
  112. catch (Exception e)
  113. {
  114. if (Fx.IsFatal(e))
  115. {
  116. throw;
  117. }
  118. completionException = e;
  119. }
  120. thisPtr.Complete(false, completionException);
  121. }
  122. }
  123. static Exception CreateReceiveRequestTimedOutException(IReplyChannel channel, TimeSpan timeout)
  124. {
  125. if (channel.LocalAddress != null)
  126. {
  127. return new TimeoutException(SR.GetString(SR.ReceiveRequestTimedOut, channel.LocalAddress.Uri.AbsoluteUri, timeout));
  128. }
  129. else
  130. {
  131. return new TimeoutException(SR.GetString(SR.ReceiveRequestTimedOutNoLocalAddress, timeout));
  132. }
  133. }
  134. #endregion
  135. public RequestContext ReceiveRequest()
  136. {
  137. return this.ReceiveRequest(this.DefaultReceiveTimeout);
  138. }
  139. public RequestContext ReceiveRequest(TimeSpan timeout)
  140. {
  141. if (timeout < TimeSpan.Zero)
  142. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  143. new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
  144. this.ThrowPending();
  145. return ReplyChannel.HelpReceiveRequest(this, timeout);
  146. }
  147. public IAsyncResult BeginReceiveRequest(AsyncCallback callback, object state)
  148. {
  149. return this.BeginReceiveRequest(this.DefaultReceiveTimeout, callback, state);
  150. }
  151. public IAsyncResult BeginReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
  152. {
  153. if (timeout < TimeSpan.Zero)
  154. {
  155. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  156. new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
  157. }
  158. this.ThrowPending();
  159. return ReplyChannel.HelpBeginReceiveRequest(this, timeout, callback, state);
  160. }
  161. public RequestContext EndReceiveRequest(IAsyncResult result)
  162. {
  163. return ReplyChannel.HelpEndReceiveRequest(result);
  164. }
  165. public bool TryReceiveRequest(TimeSpan timeout, out RequestContext context)
  166. {
  167. if (timeout < TimeSpan.Zero)
  168. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  169. new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
  170. this.ThrowPending();
  171. return base.Dequeue(timeout, out context);
  172. }
  173. public IAsyncResult BeginTryReceiveRequest(TimeSpan timeout, AsyncCallback callback, object state)
  174. {
  175. if (timeout < TimeSpan.Zero)
  176. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  177. new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
  178. this.ThrowPending();
  179. return base.BeginDequeue(timeout, callback, state);
  180. }
  181. public bool EndTryReceiveRequest(IAsyncResult result, out RequestContext context)
  182. {
  183. return base.EndDequeue(result, out context);
  184. }
  185. public bool WaitForRequest(TimeSpan timeout)
  186. {
  187. if (timeout < TimeSpan.Zero)
  188. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  189. new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
  190. this.ThrowPending();
  191. return base.WaitForItem(timeout);
  192. }
  193. public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state)
  194. {
  195. if (timeout < TimeSpan.Zero)
  196. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  197. new ArgumentOutOfRangeException("timeout", timeout, SR.GetString(SR.SFxTimeoutOutOfRange0)));
  198. this.ThrowPending();
  199. return base.BeginWaitForItem(timeout, callback, state);
  200. }
  201. public bool EndWaitForRequest(IAsyncResult result)
  202. {
  203. return base.EndWaitForItem(result);
  204. }
  205. }
  206. }