33using System . Net . Http ;
44using System . Reflection ;
55using System . Runtime . ExceptionServices ;
6+ using System . Threading ;
67using System . Threading . Tasks ;
78using SocketLabs . InjectionApi . Core ;
89using SocketLabs . InjectionApi . Message ;
@@ -193,6 +194,7 @@ public static SendResponse QuickSend(
193194 /// Asynchronously sends a basic email message and returns the response from the Injection API.
194195 /// </summary>
195196 /// <param name="message">A <c>BasicMessage</c> object to be sent.</param>
197+ /// <param name="cancellationToken">A <c>CancellationToken</c> to handle cancellation between async threads.</param>
196198 /// <returns>A <c>SendResponse</c> of an SocketLabsClient send request.</returns>
197199 /// <example>
198200 /// This sample shows you how to Send a Basic Message
@@ -216,31 +218,39 @@ public static SendResponse QuickSend(
216218 /// }
217219 ///</code>
218220 /// </example>
219- public async Task < SendResponse > SendAsync ( IBasicMessage message )
220- {
221- var validator = new SendValidator ( ) ;
221+ public async Task < SendResponse > SendAsync ( IBasicMessage message , CancellationToken cancellationToken )
222+ {
223+ try
224+ {
225+ var validator = new SendValidator ( ) ;
222226
223- var validationResult = validator . ValidateCredentials ( _serverId , _apiKey ) ;
224- if ( validationResult . Result != SendResult . Success ) return validationResult ;
225-
226- validationResult = validator . ValidateMessage ( message ) ;
227- if ( validationResult . Result != SendResult . Success ) return validationResult ;
227+ var validationResult = validator . ValidateCredentials ( _serverId , _apiKey ) ;
228+ if ( validationResult . Result != SendResult . Success ) return validationResult ;
228229
229- var factory = new InjectionRequestFactory ( _serverId , _apiKey ) ;
230- var injectionRequest = factory . GenerateRequest ( message ) ;
231- var json = injectionRequest . GetAsJson ( ) ;
230+ validationResult = validator . ValidateMessage ( message ) ;
231+ if ( validationResult . Result != SendResult . Success ) return validationResult ;
232232
233- _httpClient . Timeout = TimeSpan . FromSeconds ( RequestTimeout ) ;
234- var httpResponse = await _httpClient . PostAsync ( EndpointUrl , json ) ;
233+ var factory = new InjectionRequestFactory ( _serverId , _apiKey ) ;
234+ var injectionRequest = factory . GenerateRequest ( message ) ;
235+ var json = injectionRequest . GetAsJson ( ) ;
235236
236- var response = new InjectionResponseParser ( ) . Parse ( httpResponse ) ;
237- return response ;
237+ _httpClient . Timeout = TimeSpan . FromSeconds ( RequestTimeout ) ;
238+ var httpResponse = await _httpClient . PostAsync ( EndpointUrl , json , cancellationToken ) ;
239+
240+ var response = new InjectionResponseParser ( ) . Parse ( httpResponse ) ;
241+ return response ;
242+ }
243+ catch ( OperationCanceledException ) when ( ! cancellationToken . IsCancellationRequested )
244+ {
245+ throw new TimeoutException ( ) ;
246+ }
238247 }
239-
248+
240249 /// <summary>
241250 /// Asynchronously sends a bulk email message and returns the response from the Injection API.
242251 /// </summary>
243252 /// <param name="message">A <c>BulkMessage</c> object to be sent.</param>
253+ /// <param name="cancellationToken">A <c>CancellationToken</c> to handle cancellation between async threads.</param>
244254 /// <returns>A <c>SendResponse</c> of an SocketLabsClient send request.</returns>
245255 /// <example>
246256 /// This sample shows you how to Send a Bulk Message
@@ -268,24 +278,31 @@ public async Task<SendResponse> SendAsync(IBasicMessage message)
268278 /// }
269279 ///</code>
270280 /// </example>
271- public async Task < SendResponse > SendAsync ( IBulkMessage message )
281+ public async Task < SendResponse > SendAsync ( IBulkMessage message , CancellationToken cancellationToken )
272282 {
273- var validator = new SendValidator ( ) ;
283+ try
284+ {
285+ var validator = new SendValidator ( ) ;
274286
275- var validationResult = validator . ValidateCredentials ( _serverId , _apiKey ) ;
276- if ( validationResult . Result != SendResult . Success ) return validationResult ;
287+ var validationResult = validator . ValidateCredentials ( _serverId , _apiKey ) ;
288+ if ( validationResult . Result != SendResult . Success ) return validationResult ;
277289
278- validationResult = validator . ValidateMessage ( message ) ;
279- if ( validationResult . Result != SendResult . Success ) return validationResult ;
290+ validationResult = validator . ValidateMessage ( message ) ;
291+ if ( validationResult . Result != SendResult . Success ) return validationResult ;
280292
281- var factory = new InjectionRequestFactory ( _serverId , _apiKey ) ;
282- var injectionRequest = factory . GenerateRequest ( message ) ;
293+ var factory = new InjectionRequestFactory ( _serverId , _apiKey ) ;
294+ var injectionRequest = factory . GenerateRequest ( message ) ;
283295
284- _httpClient . Timeout = TimeSpan . FromSeconds ( RequestTimeout ) ;
285- var httpResponse = await _httpClient . PostAsync ( EndpointUrl , injectionRequest . GetAsJson ( ) ) ;
296+ _httpClient . Timeout = TimeSpan . FromSeconds ( RequestTimeout ) ;
297+ var httpResponse = await _httpClient . PostAsync ( EndpointUrl , injectionRequest . GetAsJson ( ) , cancellationToken ) ;
286298
287- var response = new InjectionResponseParser ( ) . Parse ( httpResponse ) ;
288- return response ;
299+ var response = new InjectionResponseParser ( ) . Parse ( httpResponse ) ;
300+ return response ;
301+ }
302+ catch ( OperationCanceledException ) when ( ! cancellationToken . IsCancellationRequested )
303+ {
304+ throw new TimeoutException ( ) ;
305+ }
289306 }
290307
291308 /// <summary>
@@ -319,8 +336,15 @@ public SendResponse Send(IBasicMessage message)
319336 {
320337 try
321338 {
339+ var source = new CancellationTokenSource ( ) ;
322340 //Read this if you have questions: https://blogs.msdn.microsoft.com/pfxteam/2012/04/13/should-i-expose-synchronous-wrappers-for-asynchronous-methods/
323- return Task . Run ( ( ) => SendAsync ( message ) ) . Result ;
341+ var sendTask = Task . Run ( ( ) => SendAsync ( message , source . Token ) ) ;
342+
343+ while ( ! sendTask . IsCompleted ) { }
344+ if ( sendTask . Status == TaskStatus . Faulted ) throw sendTask . Exception ;
345+
346+ return sendTask . Result ;
347+
324348 }
325349 //for synchronous usage, try to simplify exceptions being thrown
326350 catch ( AggregateException e )
@@ -366,9 +390,15 @@ public SendResponse Send(IBulkMessage message)
366390 {
367391 try
368392 {
393+ var source = new CancellationTokenSource ( ) ;
394+
369395 //Read this if you have questions: https://blogs.msdn.microsoft.com/pfxteam/2012/04/13/should-i-expose-synchronous-wrappers-for-asynchronous-methods/
370- return Task . Run ( ( ) => SendAsync ( message ) ) . Result ;
396+ var sendTask = Task . Run ( ( ) => SendAsync ( message , source . Token ) ) ;
397+
398+ while ( ! sendTask . IsCompleted ) { }
399+ if ( sendTask . Status == TaskStatus . Faulted ) throw sendTask . Exception ;
371400
401+ return sendTask . Result ;
372402 }
373403 //for synchronous usage, try to simplify exceptions being thrown
374404 catch ( AggregateException e )
@@ -386,5 +416,7 @@ public void Dispose()
386416 {
387417 _httpClient ? . Dispose ( ) ;
388418 }
419+
420+
389421 }
390422}
0 commit comments