1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Threading.Tasks; 6 using Xunit; 7 8 namespace System.Threading.Tests 9 { 10 public static class SemaphoreSlimCancellationTests 11 { 12 [Fact] CancelBeforeWait()13 public static void CancelBeforeWait() 14 { 15 SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); 16 17 CancellationTokenSource cs = new CancellationTokenSource(); 18 cs.Cancel(); 19 CancellationToken ct = cs.Token; 20 21 const int millisec = 100; 22 TimeSpan timeSpan = new TimeSpan(100); 23 EnsureOperationCanceledExceptionThrown(() => semaphoreSlim.Wait(ct), ct, "CancelBeforeWait: An OCE should have been thrown."); 24 EnsureOperationCanceledExceptionThrown(() => semaphoreSlim.Wait(millisec, ct), ct, "CancelBeforeWait: An OCE should have been thrown."); 25 EnsureOperationCanceledExceptionThrown(() => semaphoreSlim.Wait(timeSpan, ct), ct, "CancelBeforeWait: An OCE should have been thrown."); 26 semaphoreSlim.Dispose(); 27 } 28 29 [Fact] CancelAfterWait()30 public static void CancelAfterWait() 31 { 32 CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); 33 CancellationToken cancellationToken = cancellationTokenSource.Token; 34 35 SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0); // semaphore that will block all waiters 36 37 Task.Run( 38 () => 39 { 40 for (int i = 0; i < 300; i++) ; 41 cancellationTokenSource.Cancel(); 42 }); 43 44 //Now wait.. the wait should abort and an exception should be thrown 45 EnsureOperationCanceledExceptionThrown( 46 () => semaphoreSlim.Wait(cancellationToken), 47 cancellationToken, "CancelAfterWait: An OCE(null) should have been thrown that references the cancellationToken."); 48 49 // the token should not have any listeners. 50 // currently we don't expose this.. but it was verified manually 51 } 52 EnsureOperationCanceledExceptionThrown(Action action, CancellationToken token, string message)53 private static void EnsureOperationCanceledExceptionThrown(Action action, CancellationToken token, string message) 54 { 55 OperationCanceledException operationCanceledEx = 56 Assert.Throws<OperationCanceledException>(action); 57 Assert.Equal(token, operationCanceledEx.CancellationToken); 58 } 59 } 60 } 61