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