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.Runtime.CompilerServices; 21 using System.Threading.Tasks; 22 23 namespace Grpc.Core 24 { 25 /// <summary> 26 /// Return type for client streaming calls. 27 /// </summary> 28 /// <typeparam name="TRequest">Request message type for this call.</typeparam> 29 /// <typeparam name="TResponse">Response message type for this call.</typeparam> 30 public sealed class AsyncClientStreamingCall<TRequest, TResponse> : IDisposable 31 { 32 readonly IClientStreamWriter<TRequest> requestStream; 33 readonly Task<TResponse> responseAsync; 34 readonly Task<Metadata> responseHeadersAsync; 35 readonly Func<Status> getStatusFunc; 36 readonly Func<Metadata> getTrailersFunc; 37 readonly Action disposeAction; 38 39 /// <summary> 40 /// Creates a new AsyncClientStreamingCall object with the specified properties. 41 /// </summary> 42 /// <param name="requestStream">Stream of request values.</param> 43 /// <param name="responseAsync">The response of the asynchronous call.</param> 44 /// <param name="responseHeadersAsync">Response headers of the asynchronous call.</param> 45 /// <param name="getStatusFunc">Delegate returning the status of the call.</param> 46 /// <param name="getTrailersFunc">Delegate returning the trailing metadata of the call.</param> 47 /// <param name="disposeAction">Delegate to invoke when Dispose is called on the call object.</param> AsyncClientStreamingCall(IClientStreamWriter<TRequest> requestStream, Task<TResponse> responseAsync, Task<Metadata> responseHeadersAsync, Func<Status> getStatusFunc, Func<Metadata> getTrailersFunc, Action disposeAction)48 public AsyncClientStreamingCall(IClientStreamWriter<TRequest> requestStream, 49 Task<TResponse> responseAsync, 50 Task<Metadata> responseHeadersAsync, 51 Func<Status> getStatusFunc, 52 Func<Metadata> getTrailersFunc, 53 Action disposeAction) 54 { 55 this.requestStream = requestStream; 56 this.responseAsync = responseAsync; 57 this.responseHeadersAsync = responseHeadersAsync; 58 this.getStatusFunc = getStatusFunc; 59 this.getTrailersFunc = getTrailersFunc; 60 this.disposeAction = disposeAction; 61 } 62 63 /// <summary> 64 /// Asynchronous call result. 65 /// </summary> 66 public Task<TResponse> ResponseAsync 67 { 68 get 69 { 70 return this.responseAsync; 71 } 72 } 73 74 /// <summary> 75 /// Asynchronous access to response headers. 76 /// </summary> 77 public Task<Metadata> ResponseHeadersAsync 78 { 79 get 80 { 81 return this.responseHeadersAsync; 82 } 83 } 84 85 /// <summary> 86 /// Async stream to send streaming requests. 87 /// </summary> 88 public IClientStreamWriter<TRequest> RequestStream 89 { 90 get 91 { 92 return requestStream; 93 } 94 } 95 96 /// <summary> 97 /// Allows awaiting this object directly. 98 /// </summary> 99 /// <returns></returns> GetAwaiter()100 public TaskAwaiter<TResponse> GetAwaiter() 101 { 102 return responseAsync.GetAwaiter(); 103 } 104 105 /// <summary> 106 /// Gets the call status if the call has already finished. 107 /// Throws InvalidOperationException otherwise. 108 /// </summary> GetStatus()109 public Status GetStatus() 110 { 111 return getStatusFunc(); 112 } 113 114 /// <summary> 115 /// Gets the call trailing metadata if the call has already finished. 116 /// Throws InvalidOperationException otherwise. 117 /// </summary> GetTrailers()118 public Metadata GetTrailers() 119 { 120 return getTrailersFunc(); 121 } 122 123 /// <summary> 124 /// Provides means to cleanup after the call. 125 /// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything. 126 /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. 127 /// As a result, all resources being used by the call should be released eventually. 128 /// </summary> 129 /// <remarks> 130 /// Normally, there is no need for you to dispose the call unless you want to utilize the 131 /// "Cancel" semantics of invoking <c>Dispose</c>. 132 /// </remarks> Dispose()133 public void Dispose() 134 { 135 disposeAction.Invoke(); 136 } 137 } 138 } 139