///<summary> ///Sends a single message synchronously, blocking until the send is complete. Does not wait for ///a response. ///<c> ///NOTE: the underlying transport may be non-blocking, in which case the blocking is simulated ///by waits instead of using blocking network operations. ///</c> ///</summary> ///<exception cref="Thrift.TException"> ///if a network or protocol error occurs while serializing or sending the request ///</exception> public static void SendSynchronousOneWayMessage(this IRequestChannel channel, IByteBuffer request) { TException exceptionHolder = null; request.Retain(); using (ManualResetEventSlim latch = new ManualResetEventSlim(false)) { channel.SendAsynchronousRequest(request, true, new RequestListener( onRequestSent: reqs => { reqs?.Release(); latch.Set(); }, //onResponseReceive: response => //{ // communicatingComplete?.Invoke(); // latch.Set(); //}, onChannelError: e => { exceptionHolder = e; latch.Set(); })); if (!latch.Wait(TimeSpan.FromMinutes(10))) { throw new TException("wait for one-way request sent timeout."); } } if (exceptionHolder != null) { throw exceptionHolder; } }
///<summary> ///Sends a single message synchronously, and blocks until the responses is received. ///</summary> ///<remarks> ///NOTE: the underlying transport may be non-blocking, in which case the blocking is simulated ///by waits instead of using blocking network operations. ///</remarks> ///<returns>The response, stored in a <see cref="IByteBuffer"/></returns> ///<exception cref="Thrift.TException"> /// if an error occurs while serializing or sending the request or while receiving or de-serializing the response /// </exception> public static IByteBuffer SendSynchronousTwoWayMessage(this IRequestChannel channel, IByteBuffer request) { request?.Retain(); IByteBuffer responseHolder = null; TException exceptionHolder = null; using (ManualResetEventSlim latch = new ManualResetEventSlim(false)) { channel.SendAsynchronousRequest(request, false, new RequestListener( onRequestSent: reqs => { reqs?.Release(); }, onResponseReceive: response => { responseHolder = response; latch.Set(); }, onChannelError: e => { exceptionHolder = e; latch.Set(); } )); if (!latch.Wait(TimeSpan.FromMinutes(10))) { throw new TException("wait for response/error timeout."); } } if (exceptionHolder != null) { throw exceptionHolder; } return(responseHolder); }
public Task AsynchronousInvoke( IRequestChannel channel, TChannelBufferInputTransport inputTransport, TChannelBufferOutputTransport outputTransport, TProtocol inputProtocol, TProtocol outputProtocol, int sequenceId, ClientContextChain contextChain, Object[] args) { //Mark: 微软没有提供 TaskCompletionSource 的非泛型类型,只能使用动态类型处理。 TaskCompletionSourceEx future; if (_successCodec.Type != ThriftType.Void) { future = new TaskCompletionSourceEx(_successCodec.Type.CSharpType); } else { future = new TaskCompletionSourceEx(typeof(Object)); } var requestContext = RequestContexts.GetCurrentContext(); contextChain.PreWrite(args); outputTransport.ResetOutputBuffer(); WriteArguments(outputProtocol, sequenceId, args); IByteBuffer requestBuffer = outputTransport.OutputBuffer.Copy(); contextChain.PostWrite(args); requestBuffer.Retain(); channel.SendAsynchronousRequest(requestBuffer, false, new RequestListener( onRequestSent: reqs => { reqs.Release(); if (this._oneway) { try { ForceDoneChain(contextChain); future.TrySetResult(null); } catch (Exception e) { ForceDoneChain(contextChain); future.TrySetException(e); } } }, onResponseReceive: message => { IRequestContext oldRequestContext = RequestContexts.GetCurrentContext(); RequestContexts.SetCurrentContext(requestContext); try { contextChain.PreRead(); inputTransport.SetInputBuffer(message); WaitForResponse(inputProtocol, sequenceId); Object results = ReadResponse(inputProtocol); contextChain.PostRead(results); ForceDoneChain(contextChain); future.TrySetResult(results); } catch (Exception e) { var wrapException = ThriftClientManager.WrapTException(e); contextChain.PostReadException(e); ForceDoneChain(contextChain); future.TrySetException(wrapException); } finally { RequestContexts.SetCurrentContext(oldRequestContext); } }, onChannelError: e => { if (requestBuffer.ReferenceCount > 0) { requestBuffer.Release(); } IRequestContext oldRequestContext = RequestContexts.GetCurrentContext(); RequestContexts.SetCurrentContext(requestContext); try { contextChain.PreReadException(e); ForceDoneChain(contextChain); var wrappedException = ThriftClientManager.WrapTException(e); future.TrySetException(wrappedException); } finally { RequestContexts.SetCurrentContext(oldRequestContext); } } )); return(future.Task); }