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