1 #region Copyright notice and license 2 3 // Copyright 2015 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using System.Threading.Tasks; 21 22 namespace Grpc.Core 23 { 24 /// <summary> 25 /// Return type for bidirectional streaming calls. 26 /// </summary> 27 /// <typeparam name="TRequest">Request message type for this call.</typeparam> 28 /// <typeparam name="TResponse">Response message type for this call.</typeparam> 29 public sealed class AsyncDuplexStreamingCall<TRequest, TResponse> : IDisposable 30 { 31 readonly IClientStreamWriter<TRequest> requestStream; 32 readonly IAsyncStreamReader<TResponse> responseStream; 33 readonly AsyncCallState callState; 34 35 /// <summary> 36 /// Creates a new AsyncDuplexStreamingCall object with the specified properties. 37 /// </summary> 38 /// <param name="requestStream">Stream of request values.</param> 39 /// <param name="responseStream">Stream of response values.</param> 40 /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param> 41 /// <param name="getStatusFunc">Delegate returning the status of the call.</param> 42 /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param> 43 /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param> AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream, IAsyncStreamReader<TResponse> responseStream, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)44 public AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream, 45 IAsyncStreamReader<TResponse> responseStream, 46 Task<Metadata> responseHeadersAsync, 47 Func<Status> getStatusFunc, 48 Func<Metadata> getTrailersFunc, 49 Action disposeAction) 50 { 51 this.requestStream = requestStream; 52 this.responseStream = responseStream; 53 this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); 54 } 55 56 /// <summary> 57 /// Creates a new AsyncDuplexStreamingCall object with the specified properties. 58 /// </summary> 59 /// <param name="requestStream">Stream of request values.</param> 60 /// <param name="responseStream">Stream of response values.</param> 61 /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param> 62 /// <param name="getStatusFunc">Delegate returning the status of the call.</param> 63 /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param> 64 /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param> 65 /// <param name="state">State object for use with the callback parameters.</param> AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream, IAsyncStreamReader<TResponse> responseStream, Func<object, Task<Metadata>> responseHeadersAsync, Func<object, Status> getStatusFunc, Func<object, Metadata> getTrailersFunc, Action<object> disposeAction, object state)66 public AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream, 67 IAsyncStreamReader<TResponse> responseStream, 68 Func<object, Task<Metadata>> responseHeadersAsync, 69 Func<object, Status> getStatusFunc, 70 Func<object, Metadata> getTrailersFunc, 71 Action<object> disposeAction, 72 object state) 73 { 74 this.requestStream = requestStream; 75 this.responseStream = responseStream; 76 this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction, state); 77 } 78 79 /// <summary> 80 /// Async stream to read streaming responses. 81 /// </summary> 82 public IAsyncStreamReader<TResponse> ResponseStream 83 { 84 get 85 { 86 return responseStream; 87 } 88 } 89 90 /// <summary> 91 /// Async stream to send streaming requests. 92 /// </summary> 93 public IClientStreamWriter<TRequest> RequestStream 94 { 95 get 96 { 97 return requestStream; 98 } 99 } 100 101 /// <summary> 102 /// Asynchronous access to response headers. 103 /// </summary> 104 public Task<Metadata> ResponseHeadersAsync 105 { 106 get 107 { 108 return callState.ResponseHeadersAsync(); 109 } 110 } 111 112 /// <summary> 113 /// Gets the call status if the call has already finished. 114 /// Throws InvalidOperationException otherwise. 115 /// </summary> GetStatus()116 public Status GetStatus() 117 { 118 return callState.GetStatus(); 119 } 120 121 /// <summary> 122 /// Gets the call trailing metadata if the call has already finished. 123 /// Throws InvalidOperationException otherwise. 124 /// </summary> GetTrailers()125 public Metadata GetTrailers() 126 { 127 return callState.GetTrailers(); 128 } 129 130 /// <summary> 131 /// Provides means to cleanup after the call. 132 /// If the call has already finished normally (request stream has been completed and response stream has been fully read), doesn't do anything. 133 /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. 134 /// As a result, all resources being used by the call should be released eventually. 135 /// </summary> 136 /// <remarks> 137 /// Normally, there is no need for you to dispose the call unless you want to utilize the 138 /// "Cancel" semantics of invoking <c>Dispose</c>. 139 /// </remarks> Dispose()140 public void Dispose() 141 { 142 callState.Dispose(); 143 } 144 } 145 } 146