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 Task<Metadata> responseHeadersAsync; 34 readonly Func<Status> getStatusFunc; 35 readonly Func<Metadata> getTrailersFunc; 36 readonly Action disposeAction; 37 38 /// <summary> 39 /// Creates a new AsyncDuplexStreamingCall object with the specified properties. 40 /// </summary> 41 /// <param name="requestStream">Stream of request values.</param> 42 /// <param name="responseStream">Stream of response values.</param> 43 /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param> 44 /// <param name="getStatusFunc">Delegate returning the status of the call.</param> 45 /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param> 46 /// <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)47 public AsyncDuplexStreamingCall(IClientStreamWriter<TRequest> requestStream, 48 IAsyncStreamReader<TResponse> responseStream, 49 Task<Metadata> responseHeadersAsync, 50 Func<Status> getStatusFunc, 51 Func<Metadata> getTrailersFunc, 52 Action disposeAction) 53 { 54 this.requestStream = requestStream; 55 this.responseStream = responseStream; 56 this.responseHeadersAsync = responseHeadersAsync; 57 this.getStatusFunc = getStatusFunc; 58 this.getTrailersFunc = getTrailersFunc; 59 this.disposeAction = disposeAction; 60 } 61 62 /// <summary> 63 /// Async stream to read streaming responses. 64 /// </summary> 65 public IAsyncStreamReader<TResponse> ResponseStream 66 { 67 get 68 { 69 return responseStream; 70 } 71 } 72 73 /// <summary> 74 /// Async stream to send streaming requests. 75 /// </summary> 76 public IClientStreamWriter<TRequest> RequestStream 77 { 78 get 79 { 80 return requestStream; 81 } 82 } 83 84 /// <summary> 85 /// Asynchronous access to response headers. 86 /// </summary> 87 public Task<Metadata> ResponseHeadersAsync 88 { 89 get 90 { 91 return this.responseHeadersAsync; 92 } 93 } 94 95 /// <summary> 96 /// Gets the call status if the call has already finished. 97 /// Throws InvalidOperationException otherwise. 98 /// </summary> GetStatus()99 public Status GetStatus() 100 { 101 return getStatusFunc(); 102 } 103 104 /// <summary> 105 /// Gets the call trailing metadata if the call has already finished. 106 /// Throws InvalidOperationException otherwise. 107 /// </summary> GetTrailers()108 public Metadata GetTrailers() 109 { 110 return getTrailersFunc(); 111 } 112 113 /// <summary> 114 /// Provides means to cleanup after the call. 115 /// If the call has already finished normally (request stream has been completed and response stream has been fully read), doesn't do anything. 116 /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. 117 /// As a result, all resources being used by the call should be released eventually. 118 /// </summary> 119 /// <remarks> 120 /// Normally, there is no need for you to dispose the call unless you want to utilize the 121 /// "Cancel" semantics of invoking <c>Dispose</c>. 122 /// </remarks> Dispose()123 public void Dispose() 124 { 125 disposeAction.Invoke(); 126 } 127 } 128 } 129