public static void RunSpinLockTest0_Enter(int threadsCount, bool enableThreadIDs) { // threads array Task[] threads = new Task[threadsCount]; //spinlock object SpinLock slock = new SpinLock(enableThreadIDs); // succeeded threads counter int succeeded = 0; // Semaphore used to make sure that there is no other threads in the critical section SemaphoreSlim semaphore = new SemaphoreSlim(1, 1); for (int i = 0; i < threadsCount; i++) { threads[i] = Task.Run(delegate () { bool lockTaken = false; try { slock.Enter(ref lockTaken); //use semaphore to make sure that no other thread inside the critical section if (!semaphore.Wait(0)) { // This mean that there is another thread in the critical section return; } succeeded++; if (slock.IsThreadOwnerTrackingEnabled && !slock.IsHeldByCurrentThread) { // lock is obtained successfully succeeded--; } } catch { // decrement the count in case of exception succeeded--; } finally { semaphore.Release(); if (lockTaken) { slock.Exit(); } } }); } // wait all threads for (int i = 0; i < threadsCount; i++) { threads[i].Wait(); } // count must be equal to the threads count Assert.Equal(threadsCount, succeeded); }
/// <summary> /// Test SemaphoreSlim Release /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="releaseCount">The release count for the release method</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest2_Release (int initial, int maximum, int releaseCount, Type exceptionType) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { int oldCount = semaphore.Release(releaseCount); Assert.Equal(initial, oldCount); Assert.Equal(initial + releaseCount, semaphore.CurrentCount); } catch (Exception ex) { Assert.NotNull(exceptionType); Assert.IsType(exceptionType, ex); } }
public static void CancelAfterWait() { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0); // semaphore that will block all waiters Task.Run( () => { for (int i = 0; i < 300; i++) ; cancellationTokenSource.Cancel(); }); //Now wait.. the wait should abort and an exception should be thrown EnsureOperationCanceledExceptionThrown( () => semaphoreSlim.Wait(cancellationToken), cancellationToken, "CancelAfterWait: An OCE(null) should have been thrown that references the cancellationToken."); // the token should not have any listeners. // currently we don't expose this.. but it was verified manually }
/// <summary> /// Test SemaphoreSlim AvailableWaitHandle property /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="action">SemaphoreSlim action to be called before WaitHandle</param> /// <param name="state">The expected wait handle state</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest7_AvailableWaitHandle(int initial, int maximum, SemaphoreSlimActions? action, bool state) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { CallSemaphoreAction(semaphore, action, null); if (semaphore.AvailableWaitHandle == null) { string methodFailed = "RunSemaphoreSlimTest7_AvailableWaitHandle(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "AvailableWaitHandle failed, handle is null.")); } if (semaphore.AvailableWaitHandle.WaitOne(0) != state) { string methodFailed = "RunSemaphoreSlimTest7_AvailableWaitHandle(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "AvailableWaitHandle failed, expected " + state + " actual " + !state)); } } catch (Exception ex) { string methodFailed = "RunSemaphoreSlimTest7_AvailableWaitHandle(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "AvailableWaitHandle failed, the code threw exception " + ex)); } }
public static void CancelBeforeWait() { SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); CancellationTokenSource cs = new CancellationTokenSource(); cs.Cancel(); CancellationToken ct = cs.Token; const int millisec = 100; TimeSpan timeSpan = new TimeSpan(100); EnsureOperationCanceledExceptionThrown(() => semaphoreSlim.Wait(ct), ct, "CancelBeforeWait: An OCE should have been thrown."); EnsureOperationCanceledExceptionThrown(() => semaphoreSlim.Wait(millisec, ct), ct, "CancelBeforeWait: An OCE should have been thrown."); EnsureOperationCanceledExceptionThrown(() => semaphoreSlim.Wait(timeSpan, ct), ct, "CancelBeforeWait: An OCE should have been thrown."); semaphoreSlim.Dispose(); }
public static SemaphoreDisposer DisposableWait(this SemaphoreSlim semaphore, CancellationToken cancellationToken = default) { semaphore.Wait(cancellationToken); return(new SemaphoreDisposer(semaphore)); }
/// <summary> /// Initializes a new instance of the <see cref="Semaphore"/> class. /// </summary> protected Semaphore(SemaphoreSlim semaphore) { this.Instance = semaphore; }
public static Scope Lock(this SemaphoreSlim ss, TimeSpan timeout) { return(Scope.Create( () => ss.Wait(timeout), () => ss.Release())); }
static HttpRequestor() { ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12; ServicePointManager.DefaultConnectionLimit = Environment.ProcessorCount; availableConnections = new SemaphoreSlim(ServicePointManager.DefaultConnectionLimit); }
/// <summary> /// Test SemaphoreSlim WaitAsync and Release methods concurrently /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="waitThreads">Number of the threads that call Wait method</param> /// <param name="releaseThreads">Number of the threads that call Release method</param> /// <param name="succeededWait">Number of succeeded wait threads</param> /// <param name="failedWait">Number of failed wait threads</param> /// <param name="finalCount">The final semaphore count</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest8_ConcWaitAsyncAndRelease(int initial, int maximum, int waitThreads, int releaseThreads, int succeededWait, int failedWait, int finalCount, int timeout) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); Task[] tasks = new Task[waitThreads + releaseThreads]; int succeeded = 0; int failed = 0; ManualResetEvent mre = new ManualResetEvent(false); // launch threads for (int i = 0; i < tasks.Length; i++) { if (i < waitThreads) { tasks[i] = Task.Run(async delegate { mre.WaitOne(); if (await semaphore.WaitAsync(timeout)) { Interlocked.Increment(ref succeeded); } else { Interlocked.Increment(ref failed); } }); } else { tasks[i] = Task.Run(delegate { mre.WaitOne(); semaphore.Release(); }); } } mre.Set(); //wait work to be done; Task.WaitAll(tasks); Assert.Equal(succeededWait, succeeded); Assert.Equal(failedWait, failed); Assert.Equal(finalCount, semaphore.CurrentCount); }
/// <summary> /// Test SemaphoreSlim Dispose /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="action">SemaphoreSlim action to be called after Dispose</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest4_Dispose(int initial, int maximum, SemaphoreSlimActions? action, Type exceptionType) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { semaphore.Dispose(); CallSemaphoreAction(semaphore, action, null); } catch (Exception ex) { Assert.NotNull(exceptionType); Assert.IsType(exceptionType, ex); } }
/// <summary> /// Test SemaphoreSlim WaitAsync /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="timeout">The timeout parameter for the wait method, it must be either int or TimeSpan</param> /// <param name="returnValue">The expected wait return value</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest1_WaitAsync (int initial, int maximum, object timeout, bool returnValue, Type exceptionType) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { bool result = false; if (timeout is TimeSpan) { result = semaphore.WaitAsync((TimeSpan)timeout).Result; } else { result = semaphore.WaitAsync((int)timeout).Result; } Assert.Equal(returnValue, result); if (result) { Assert.Equal(initial - 1, semaphore.CurrentCount); } } catch (Exception ex) { Assert.NotNull(exceptionType); Assert.IsType(exceptionType, ex); } }
public AccessTokenProvider(IDialogService dialogService, Func <LoginViewModel> loginViewModelFactory) { this.semaphoreSlim = new SemaphoreSlim(1); this.dialogService = dialogService ?? throw new ArgumentNullException(nameof(dialogService)); this.loginViewModelFactory = loginViewModelFactory ?? throw new ArgumentNullException(nameof(loginViewModelFactory)); }
public SafeSemaphoreRelease(SemaphoreSlim currentSemaphore, SemaphoreSlim nextSemaphore, AsyncLock asyncLock) { _currentSemaphore = currentSemaphore; _nextSemaphore = nextSemaphore; _asyncLock = asyncLock; }
private async Task <IAsyncDisposable> TakeLockCoreAsync(SemaphoreSlim currentSemaphore, SafeSemaphoreRelease safeSemaphoreRelease) { await currentSemaphore.WaitAsync(); return(safeSemaphoreRelease); }
public AsyncLock() { _topLevelSemaphore = s_semaphorePool.Get(); _currentSemaphore = new AsyncLocal <SemaphoreSlim>(); }
private static async Task <Task> RunSlowAsync <TState>(this SemaphoreSlim semaphoreSlim, Func <TState, Task> callback, TState state) { await semaphoreSlim.WaitAsync(); return(RunTask(callback, semaphoreSlim, state)); }
public SemaphoreDisposer(SemaphoreSlim semaphore) { _semaphore = semaphore; }
public async static Task <SemaphoreDisposer> DisposableWaitAsync(this SemaphoreSlim semaphore, CancellationToken cancellationToken = default) { await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); return(new SemaphoreDisposer(semaphore)); }
/// <summary> /// Test SemaphoreSlim Wait and Release methods concurrently /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="waitThreads">Number of the threads that call Wait method</param> /// <param name="releaseThreads">Number of the threads that call Release method</param> /// <param name="succeededWait">Number of succeeded wait threads</param> /// <param name="failedWait">Number of failed wait threads</param> /// <param name="finalCount">The final semaphore count</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest8_ConcWaitAndRelease(int initial, int maximum, int waitThreads, int releaseThreads, int succeededWait, int failedWait, int finalCount, int timeout) { string methodFailed = "RunSemaphoreSlimTest8_ConcWaitAndRelease(" + initial + "," + maximum + "," + waitThreads + ", " + releaseThreads + ", " + succeededWait + ", " + failedWait + ", " + finalCount + ", " + timeout + "): FAILED. "; try { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); Task[] threads = new Task[waitThreads + releaseThreads]; int succeeded = 0; int failed = 0; ManualResetEvent mre = new ManualResetEvent(false); // launch threads for (int i = 0; i < threads.Length; i++) { if (i < waitThreads) { // We are creating the Task using TaskCreationOptions.LongRunning to // force usage of another thread (which will be the case on the default scheduler // with its current implementation). Without this, the release tasks will likely get // queued behind the wait tasks in the pool, making it very likely that the wait tasks // will starve the very tasks that when run would unblock them. threads[i] = new Task(delegate () { mre.WaitOne(); if (semaphore.Wait(timeout)) { Interlocked.Increment(ref succeeded); } else { Interlocked.Increment(ref failed); } }, TaskCreationOptions.LongRunning); } else { threads[i] = new Task(delegate () { mre.WaitOne(); semaphore.Release(); }); } threads[i].Start(TaskScheduler.Default); } mre.Set(); //wait work to be done; Task.WaitAll(threads); //check the number of succeeded and failed wait if (succeeded != succeededWait || failed != failedWait || semaphore.CurrentCount != finalCount) { Debug.WriteLine(methodFailed + "ConcurrentWaitRelease failed. This might not be a bug, if the system was unstable during the test."); Assert.True(false, string.Format(methodFailed + "Expected succeeded={0}, failed={1}, count={2}, but got {3}, {4}, {5}", succeededWait, failedWait, finalCount, succeeded, failed, semaphore.CurrentCount)); } } catch (Exception ex) { Assert.True(false, string.Format(methodFailed + "ConcurrentWaitRelease failed, the code threw exception " + ex)); } }
private static void TestConcurrentWaitAndWaitAsync(int syncWaiters, int asyncWaiters) { string methodFailed = "ConcurrentWaitAndWaitAsync(" + syncWaiters + "," + asyncWaiters + "): FAILED."; int totalWaiters = syncWaiters + asyncWaiters; if (totalWaiters < 2) { Assert.True(false, string.Format(methodFailed + " invalid waiter arguments... need at least 2 waiters")); } var semaphore = new SemaphoreSlim(0); Task[] tasks = new Task[totalWaiters]; const int ITERS = 10; int randSeed = (int)DateTime.Now.Ticks; for (int i = 0; i < syncWaiters; i++) { tasks[i] = Task.Run(delegate { //Random rand = new Random(Interlocked.Increment(ref randSeed)); for (int iter = 0; iter < ITERS; iter++) { semaphore.Wait(); semaphore.Release(); } }); } for (int i = syncWaiters; i < totalWaiters; i++) { tasks[i] = Task.Run(async delegate { //Random rand = new Random(Interlocked.Increment(ref randSeed)); for (int iter = 0; iter < ITERS; iter++) { await semaphore.WaitAsync(); semaphore.Release(); } }); } semaphore.Release(totalWaiters / 2); Task.WaitAll(tasks); }
public CreatePerformance(IInstrumentation instrumentation, int maxConcurrentRequests, CancellationToken cancellationToken) { this.cancellationToken = cancellationToken; this.instrumentation = instrumentation; this.semaphore = new SemaphoreSlim(maxConcurrentRequests, maxConcurrentRequests); }
public SocketGroup(Dictionary <UdpClient, List <IPAddress> > sockets, int defaultPort) { Sockets = sockets; DefaultPort = defaultPort; SocketSendLocker = new SemaphoreSlim(1, 1); }
public WaitQueue(int count) { _semaphore = new SemaphoreSlim(count); }
/// <summary> /// Test SemaphoreSlim AvailableWaitHandle property /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="action">SemaphoreSlim action to be called before WaitHandle</param> /// <param name="state">The expected wait handle state</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest7_AvailableWaitHandle(int initial, int maximum, SemaphoreSlimActions? action, bool state) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); CallSemaphoreAction(semaphore, action, null); Assert.NotNull(semaphore.AvailableWaitHandle); Assert.Equal(state, semaphore.AvailableWaitHandle.WaitOne(0)); }
public SemaphoreLockStruct(SemaphoreSlim sem) { this.sem = sem; }
public static SemaphoreLockStruct Lock(this SemaphoreSlim sem) { sem.Wait(); return(new SemaphoreLockStruct(sem)); }
/// <summary> /// Test SemaphoreSlim constructor /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest0_Ctor(int initial, int maximum, Type exceptionType) { string methodFailed = "RunSemaphoreSlimTest0_Ctor(" + initial + "," + maximum + "): FAILED. "; Exception exception = null; try { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); if (semaphore.CurrentCount != initial) { Assert.True(false, string.Format(methodFailed + "Constructor test failed, expected " + initial + " actual " + semaphore.CurrentCount)); } } catch (Exception ex) { exception = ex; } // The code threw excption and it is not expected because the excyptionType param is null if (exceptionType == null && exception != null) { Assert.True(false, string.Format(methodFailed + "Constructor failed, the code threw an exception, and it is not supposed to.")); } // Compare both exception types in case of the code threw exception if (exception != null && !Type.Equals(exception.GetType(), exceptionType)) { Assert.True(false, string.Format(methodFailed + "Constructor failed, Excption types do not match")); } }
public static Scope Lock(this SemaphoreSlim ss, int timeout_ms) { return(Scope.Create( () => ss.Wait(timeout_ms), () => ss.Release())); }
/// <summary> /// Test SemaphoreSlim Release /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="releaseCount">The release count for the release method</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest2_Release (int initial, int maximum, int releaseCount, Type exceptionType) { string methodFailed = "RunSemaphoreSlimTest2_Release(" + initial + "," + maximum + "," + releaseCount + "): FAILED. "; Exception exception = null; SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { int oldCount = semaphore.Release(releaseCount); if (semaphore.CurrentCount != initial + releaseCount || oldCount != initial) { Assert.True(false, string.Format(methodFailed + "Release failed, the method returned " + oldCount + " and expected " + initial)); } } catch (Exception ex) { exception = ex; } // The code threw excption and it is not expected because the excyptionType param is null if (exceptionType == null && exception != null) { Assert.True(false, string.Format(methodFailed + "Release failed, the code threw an exception, and it is not supposed to.")); } // Compare both exception types in case of the code threw exception if (exception != null && !Type.Equals(exception.GetType(), exceptionType)) { Assert.True(false, string.Format(methodFailed + "Release failed, Excption types do not match")); } }
public static Scope Lock(this SemaphoreSlim ss, TimeSpan timeout, CancellationToken cancel) { return(Scope.Create( () => ss.Wait(timeout, cancel), () => ss.Release())); }
/// <summary> /// Test SemaphoreSlim CurrentCount property /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="action">SemaphoreSlim action to be called before CurentCount</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest5_CurrentCount(int initial, int maximum, SemaphoreSlimActions? action) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { CallSemaphoreAction(semaphore, action, null); if ((action == SemaphoreSlimActions.Wait && semaphore.CurrentCount != initial - 1) || (action == SemaphoreSlimActions.WaitAsync && semaphore.CurrentCount != initial - 1) || (action == SemaphoreSlimActions.Release && semaphore.CurrentCount != initial + 1)) { string methodFailed = "RunSemaphoreSlimTest5_CurrentCount(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "CurrentCount failed")); } } catch (Exception ex) { string methodFailed = "RunSemaphoreSlimTest5_CurrentCount(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "CurrentCount failed, the code threw exception " + ex)); } }
public async static Task <SemaphoreLockStruct> LockAsync(this SemaphoreSlim sem) { await sem.WaitAsync(); return(new SemaphoreLockStruct(sem)); }
private async Task UploadAsync(CancellationToken ct, string item, string uploadPath, SemaphoreSlim clientThrottle, bool allowOverwrite) { if (!File.Exists(item)) { throw new Exception(string.Format("The file '{0}' does not exist.", item)); } await clientThrottle.WaitAsync(); string leaseId = string.Empty; AzureBlobLease blobLease = new AzureBlobLease(feed.AccountName, feed.AccountKey, string.Empty, feed.ContainerName, uploadPath, Log, "60", "10"); bool isLeaseRequired = allowOverwrite && await feed.CheckIfBlobExists(uploadPath); if (isLeaseRequired) { try { leaseId = blobLease.Acquire(); } catch (Exception) { Log.LogError($"Unable to obtain lease on {uploadPath}"); } } try { bool isExists = await feed.CheckIfBlobExists(uploadPath); if (!isExists || allowOverwrite) { Log.LogMessage($"Uploading {item} to {uploadPath}."); UploadClient uploadClient = new UploadClient(Log); await uploadClient.UploadBlockBlobAsync( ct, feed.AccountName, feed.AccountKey, feed.ContainerName, item, uploadPath, leaseId); } else { Log.LogMessage($"Skipping uploading of {item} to {uploadPath}. Already exists."); } } catch (Exception) { Log.LogError($"Unable to upload to {uploadPath}"); } finally { if (isLeaseRequired) { blobLease.Release(); } clientThrottle.Release(); } }
/// <summary> /// Test SemaphoreSlim WaitAsync /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="timeout">The timeout parameter for the wait method, it must be either int or TimeSpan</param> /// <param name="returnValue">The expected wait return value</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest1_WaitAsync (int initial, int maximum, object timeout, bool returnValue, Type exceptionType) { string methodFailed = "RunSemaphoreSlimTest1_WaitAsync(" + initial + "," + maximum + "," + timeout + "): FAILED. "; Exception exception = null; SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { bool result = false; if (timeout is TimeSpan) { result = semaphore.WaitAsync((TimeSpan)timeout).Result; } else { result = semaphore.WaitAsync((int)timeout).Result; } if (result != returnValue || (result && semaphore.CurrentCount != initial - 1)) { Assert.True(false, string.Format(methodFailed + "WaitAsync failed, the method returned " + result + " and expected " + returnValue)); } } catch (AggregateException ex) { exception = ex.InnerException; } catch (Exception ex) { exception = ex; } // The code threw excption and it is not expected because the excyptionType param is null if (exceptionType == null && exception != null) { Assert.True(false, string.Format(methodFailed + "WaitAsync failed, the code threw an exception, and it is not supposed to.")); } // Compare both exception types in case of the code threw exception if (exception != null && !Type.Equals(exception.GetType(), exceptionType)) { Assert.True(false, string.Format(methodFailed + "WaitAsync failed, Excption types do not match")); } }
internal TreeWriter(StorageEnvironment env) { _env = env; _pendingWrites = new ConcurrentQueue <OutstandingWrite>(); _semaphore = new SemaphoreSlim(1, 1); }
/// <summary> /// Test SemaphoreSlim Dispose /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="action">SemaphoreSlim action to be called after Dispose</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest4_Dispose(int initial, int maximum, SemaphoreSlimActions? action, Type exceptionType) { Exception exception = null; SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); try { semaphore.Dispose(); CallSemaphoreAction(semaphore, action, null); } catch (Exception ex) { exception = ex; } // The code threw excption and it is not expected because the excyptionType param is null if (exceptionType == null && exception != null) { string methodFailed = "RunSemaphoreSlimTest4_Dispose(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "Dispose failed, the code threw an exception, and it is not supposed to.")); } // Compare both exception types in case of the code threw exception if (exception != null && !Type.Equals(exception.GetType(), exceptionType)) { string methodFailed = "RunSemaphoreSlimTest4_Dispose(" + initial + "," + maximum + "," + action + "): FAILED. "; Assert.True(false, string.Format(methodFailed + "Dispose failed, Excption types do not match")); } }
public ProcessLock(string name) { Name = name; Semaphore = new SemaphoreSlim(1); }
public void SendToOneChannel(object stateInfo) { var descriptor = (ChannelDescriptor)stateInfo; _identityProvider.Identity = new Identity(descriptor.CustomerCode); var channelService = ObjectFactoryBase.Resolve <INotificationChannelService>(); var config = ConfigDictionary[descriptor.CustomerCode]; try { var key = GetKey(descriptor.ChannelName, descriptor.CustomerCode); var state = _lockers[key]; if (Monitor.TryEnter(state)) { try { if (!state.BlockState.HasValue || state.BlockState.Value.AddSeconds(config.WaitIntervalAfterErrors) <= DateTime.Now) { if (state.BlockState.HasValue) { _logger.Info( "Temporary channel lock has been released for channel {channel}, customer code {customerCode}", descriptor.ChannelName, descriptor.CustomerCode ); state.BlockState = null; //снимаем блокировку, если прошел указанные интервал и пробуем отправить снова } var service = ObjectFactoryBase.Resolve <IMessageService>(); var res = service.GetMessagesToSend(descriptor.ChannelName, config.PackageSize); if (res.IsSucceeded) { var channel = GetChannel(config, descriptor.ChannelName); var semaphore = new SemaphoreSlim(Math.Max(channel.DegreeOfParallelism, 1)); var localState = new ChannelState() { ErrorsCount = 0 }; var factoryMap = res.Result.Select(m => m.Key).Distinct() .ToDictionary(k => k, k => new TaskFactory(new OrderedTaskScheduler())); var tasks = res.Result .Select(m => SendOneMessage(descriptor.CustomerCode, descriptor.InstanceId, config, channel, service, m, semaphore, factoryMap[m.Key], localState, channelService)) .ToArray(); Task.WaitAll(tasks); if (localState.ErrorsCount >= config.ErrorCountBeforeWait) { state.BlockState = DateTime.Now; _logger.Info( "Temporary channel lock has been acquired for channel {channel}, customer code {customerCode}", channel.Name, descriptor.CustomerCode ); } } else { state.BlockState = DateTime.Now; _logger.Info( "Queue for channel {channel}, customer code {customerCode} is unavailable, temporary lock will be acquired", descriptor.ChannelName, descriptor.CustomerCode ); } } } finally { Monitor.Exit(state); } } else { _logger.Info( "Queue for channel {channel}, {customerCode} is busy", descriptor.ChannelName, descriptor.CustomerCode ); } } catch (Exception ex) { _logger.Error().Exception(ex) .Message( "An error occured while processing messages from the queue for channel {channel}, customer code {customerCode}", descriptor.ChannelName, descriptor.CustomerCode ) .Write(); } }
private async Task SendOneMessage( string customerCode, string instanceId, NotificationSenderConfig config, NotificationChannel channel, IMessageService service, Message message, SemaphoreSlim semaphore, TaskFactory factory, ChannelState state, INotificationChannelService channelService) { await factory.StartNew(() => { lock (state) { if (state.ErrorsCount >= config.ErrorCountBeforeWait) { return; } } var timer = new Stopwatch(); timer.Start(); string url = GetUrl(customerCode, instanceId, channel, message); try { semaphore.Wait(); _logger.Debug("Start processing message {messageId} ", message.Id); var request = (HttpWebRequest)WebRequest.Create(url); request.Method = message.Method.ToUpper(); request.Timeout = 1000 * config.TimeOut; var mediaType = !string.IsNullOrEmpty(channel.MediaType) ? channel.MediaType : "text/xml"; request.ContentType = $"{mediaType}; charset=utf-8"; byte[] data = Encoding.UTF8.GetBytes(message.Xml); request.ContentLength = data.Length; using (var streamWriter = request.GetRequestStream()) { streamWriter.Write(data, 0, data.Length); streamWriter.Flush(); } using (var httpResponse = (HttpWebResponse)request.GetResponse()) { timer.Stop(); _logger.Info() .Message( "Message {message} for channel {channel} has been sent on url {url}", message.Method, channel.Name, Uri.UnescapeDataString(url) ) .Property("productId", message.Key) .Property("statusCode", httpResponse.StatusCode) .Property("timeTaken", timer.ElapsedMilliseconds) .Property("messageId", message.Id) .Property("customerCode", customerCode) .Write(); channelService.UpdateNotificationChannel(customerCode, channel.Name, message.Key, message.Created, httpResponse.StatusCode.ToString()); } ; service.RemoveMessage(message.Id); } catch (WebException ex) { timer.Stop(); lock (state) { state.ErrorsCount++; } var httpResponse = ex.Response as HttpWebResponse; if (httpResponse != null) { _logger.Info() .Message( "Message {message} for channel {channel} has been sent on url {url}", message.Method, channel.Name, Uri.UnescapeDataString(url) ) .Property("productId", message.Key) .Property("statusCode", httpResponse.StatusCode) .Property("timeTaken", timer.ElapsedMilliseconds) .Property("messageId", message.Id) .Property("customerCode", customerCode) .Write(); channelService.UpdateNotificationChannel(customerCode, channel.Name, message.Key, message.Created, httpResponse.StatusCode.ToString()); } else { _logger.Info() .Message( "Message {message} for channel {channel} has not been sent on url {url}", message.Method, channel.Name, Uri.UnescapeDataString(url) ) .Property("productId", message.Key) .Property("statusCode", ex.Status) .Property("timeTaken", timer.ElapsedMilliseconds) .Property("messageId", message.Id) .Property("customerCode", customerCode) .Write(); channelService.UpdateNotificationChannel(customerCode, channel.Name, message.Key, message.Created, ex.Status.ToString()); } _logger.Error().Exception(ex) .Message( "Message {message} for channel {channel} has not been sent on url {url}", message.Method, channel.Name, Uri.UnescapeDataString(url) ) .Property("productId", message.Key) .Property("timeTaken", timer.ElapsedMilliseconds) .Property("messageId", message.Id) .Property("customerCode", customerCode) .Write(); } finally { semaphore.Release(); } }); }
/// <summary> /// Test SemaphoreSlim WaitAsync and Release methods concurrently /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="waitThreads">Number of the threads that call Wait method</param> /// <param name="releaseThreads">Number of the threads that call Release method</param> /// <param name="succeededWait">Number of succeeded wait threads</param> /// <param name="failedWait">Number of failed wait threads</param> /// <param name="finalCount">The final semaphore count</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest8_ConcWaitAsyncAndRelease(int initial, int maximum, int waitThreads, int releaseThreads, int succeededWait, int failedWait, int finalCount, int timeout) { string methodFailed = "RunSemaphoreSlimTest8_ConcWaitAsyncAndRelease(" + initial + "," + maximum + "," + waitThreads + ", " + releaseThreads + "): FAILED. "; try { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); Task[] tasks = new Task[waitThreads + releaseThreads]; int succeeded = 0; int failed = 0; ManualResetEvent mre = new ManualResetEvent(false); // launch threads for (int i = 0; i < tasks.Length; i++) { if (i < waitThreads) { tasks[i] = Task.Run(async delegate { mre.WaitOne(); if (await semaphore.WaitAsync(timeout)) { Interlocked.Increment(ref succeeded); } else { Interlocked.Increment(ref failed); } }); } else { tasks[i] = Task.Run(delegate { mre.WaitOne(); semaphore.Release(); }); } } mre.Set(); //wait work to be done; Task.WaitAll(tasks); //check the number of succeeded and failed wait if (succeeded != succeededWait || failed != failedWait || semaphore.CurrentCount != finalCount) { Assert.True(false, string.Format(methodFailed + "ConcurrentWaitAsyncAndRelease failed. This might not be a bug, if the system was unstable during the test.")); } } catch (Exception ex) { Assert.True(false, string.Format(methodFailed + "ConcurrentWaitAsyncAndRelease failed, the code threw exception " + ex)); } }
public SingleThreadedFIFOSemaphoreSlim() { _inner = new SemaphoreSlim(1, 1); _queue = new ConcurrentQueue <TaskCompletionSource <bool> >(); }
/// <summary> /// Test SemaphoreSlim constructor /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="exceptionType">The type of the thrown exception in case of invalid cases, /// null for valid cases</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest0_Ctor(int initial, int maximum, Type exceptionType) { string methodFailed = "RunSemaphoreSlimTest0_Ctor(" + initial + "," + maximum + "): FAILED. "; Exception exception = null; try { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); Assert.Equal(initial, semaphore.CurrentCount); } catch (Exception ex) { Assert.NotNull(exceptionType); Assert.IsType(exceptionType, ex); exception = ex; } }
public async Task ThrottleLoadedItemsAsync <T>(ConcurrentQueue <T> queue, CancellationToken token, Func <T, Task <bool> > taskToRun, Func <T, bool, Task> taskToContinueWith, int maxConcurrentTasks = 10, int maxDegreeOfParallelism = 2) { var blockingQueue = new BlockingCollection <T>(new ConcurrentBag <T>()); var semaphore = new SemaphoreSlim(maxConcurrentTasks); var t = Task.Run(() => { try { while (true) { if (token.IsCancellationRequested) { break; } semaphore.Wait(token); if (queue.TryDequeue(out var item)) { blockingQueue.Add(item, token); } } } catch (Exception e) { ErrorHandler.HandleException(e); } blockingQueue.CompleteAdding(); }, token); var runningTasks = new List <Task>(); Parallel.ForEach(IterateUntilTrue(() => blockingQueue.IsCompleted), new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, async _ => { if (blockingQueue.TryTake(out var item, 100)) { runningTasks.Add( await taskToRun(item) .ContinueWith(tsk => { semaphore.Release(); return(taskToContinueWith(item, tsk.Result)); }, token) ); } }); while (!token.IsCancellationRequested) { while (runningTasks.Any(task => !task.IsCompleted)) { await Task.WhenAny(runningTasks); runningTasks.RemoveAll(task => task.IsCompleted); } } }
/// <summary> /// Test SemaphoreSlim WaitAsync /// The test verifies that SemaphoreSlim.Release() does not execute any user code synchronously. /// </summary> private static void RunSemaphoreSlimTest1_WaitAsync2() { SemaphoreSlim semaphore = new SemaphoreSlim(1); ThreadLocal<int> counter = new ThreadLocal<int>(() => 0); bool nonZeroObserved = false; const int asyncActions = 20; int remAsyncActions = asyncActions; ManualResetEvent mre = new ManualResetEvent(false); Action<int> doWorkAsync = async delegate (int i) { await semaphore.WaitAsync(); if (counter.Value > 0) { nonZeroObserved = true; } counter.Value = counter.Value + 1; semaphore.Release(); counter.Value = counter.Value - 1; if (Interlocked.Decrement(ref remAsyncActions) == 0) mre.Set(); }; semaphore.Wait(); for (int i = 0; i < asyncActions; i++) doWorkAsync(i); semaphore.Release(); mre.WaitOne(); Assert.False(nonZeroObserved, "RunSemaphoreSlimTest1_WaitAsync2: FAILED. SemaphoreSlim.Release() seems to have synchronously invoked a continuation."); }
async Task ProcessMessagesSwallowExceptionsAndReleaseConcurrencyLimiter(CancellationTokenSource stopBatchCancellationTokenSource, SemaphoreSlim localConcurrencyLimiter, CancellationToken messageProcessingCancellationToken) { try { try { // We need to force the method to continue asynchronously because SqlConnection // in combination with TransactionScope will apply connection pooling and enlistment synchronous in ctor. await Task.Yield(); await processStrategy.ProcessMessage(stopBatchCancellationTokenSource, messageProcessingCancellationToken) .ConfigureAwait(false); messageProcessingCircuitBreaker.Success(); } catch (SqlException ex) when(ex.Number == 1205) { // getting the message was the victim of a lock resolution Logger.Warn("Message processing failed", ex); } catch (Exception ex) when(!ex.IsCausedBy(messageProcessingCancellationToken)) { Logger.Warn("Message processing failed", ex); await messageProcessingCircuitBreaker.Failure(ex, messageProcessingCancellationToken).ConfigureAwait(false); } } catch (Exception ex) when(ex.IsCausedBy(messageProcessingCancellationToken)) { Logger.Debug("Message processing canceled.", ex); } finally { localConcurrencyLimiter.Release(); } }
/// <summary> /// Call specific SemaphoreSlim method or property /// </summary> /// <param name="semaphore">The SemaphoreSlim instance</param> /// <param name="action">The action name</param> /// <param name="param">The action parameter, null if it takes no parameters</param> /// <returns>The action return value, null if the action returns void</returns> private static object CallSemaphoreAction (SemaphoreSlim semaphore, SemaphoreSlimActions? action, object param) { if (action == SemaphoreSlimActions.Wait) { if (param is TimeSpan) { return semaphore.Wait((TimeSpan)param); } else if (param is int) { return semaphore.Wait((int)param); } semaphore.Wait(); return null; } else if (action == SemaphoreSlimActions.WaitAsync) { if (param is TimeSpan) { return semaphore.WaitAsync((TimeSpan)param).Result; } else if (param is int) { return semaphore.WaitAsync((int)param).Result; } semaphore.WaitAsync().Wait(); return null; } else if (action == SemaphoreSlimActions.Release) { if (param != null) { return semaphore.Release((int)param); } return semaphore.Release(); } else if (action == SemaphoreSlimActions.Dispose) { semaphore.Dispose(); return null; } else if (action == SemaphoreSlimActions.CurrentCount) { return semaphore.CurrentCount; } else if (action == SemaphoreSlimActions.AvailableWaitHandle) { return semaphore.AvailableWaitHandle; } return null; }
public static async Task <TResult> GetOrAddAsync <TKey, TResult>(this ConcurrentDictionary <TKey, TResult> dictionary, SemaphoreSlim lockObject, TKey key, Func <TKey, Task <TResult> > asyncValueFactory) { if (dictionary.TryGetValue(key, out var result)) { return(result); } await lockObject.WaitAsync(); try { if (dictionary.TryGetValue(key, out result)) { return(result); } return(dictionary[key] = await asyncValueFactory(key)); } finally { lockObject.Release(); } }
/// <summary> /// Test SemaphoreSlim CurrentCount property /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="action">SemaphoreSlim action to be called before CurentCount</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest5_CurrentCount(int initial, int maximum, SemaphoreSlimActions? action) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); CallSemaphoreAction(semaphore, action, null); if (action == null) { Assert.Equal(initial, semaphore.CurrentCount); } else { Assert.Equal(initial + (action == SemaphoreSlimActions.Release ? 1 : -1), semaphore.CurrentCount); } }
public async Task TheRemoteHeaderTableSizeShouldOnlyBeUsedUpToConfiguredLimit() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var handlerDone = new SemaphoreSlim(0); Func <IStream, bool> listener = (s) => { Task.Run(() => { var res = new HeaderField[] { new HeaderField { Name = ":status", Value = "200" }, }; s.WriteHeadersAsync(res, false); }); handlerDone.Release(); return(true); }; // Lower the initial window size so that stream window updates are // sent earlier than connection window updates var localSettings = Settings.Default; localSettings.HeaderTableSize = 20000; var http2Con = await ConnectionUtils.BuildEstablishedConnection( true, inPipe, outPipe, loggerProvider, listener, localSettings : localSettings); // Change remote settings, which grants us a giant header table var settings = Settings.Default; settings.HeaderTableSize = 50 * 1024 * 1024; await inPipe.WriteSettings(settings); await outPipe.AssertSettingsAck(); // Establish a stream // When we send a response through it we should observe the size udpate var hEncoder = new Encoder(); await inPipe.WriteHeaders(hEncoder, 1, false, DefaultGetHeaders); var ok = await handlerDone.WaitAsync( ReadableStreamTestExtensions.ReadTimeout); if (!ok) { throw new Exception("Stream was not created"); } // Wait for the incoming status headers with header update var fh = await outPipe.ReadFrameHeaderWithTimeout(); Assert.Equal(FrameType.Headers, fh.Type); Assert.Equal((byte)(HeadersFrameFlags.EndOfHeaders), fh.Flags); Assert.Equal(1u, fh.StreamId); // Observe headers with status update // We should update the header table to 20000 Assert.Equal(5, fh.Length); var data = new byte[fh.Length]; await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(data)); Assert.Equal(0x3f, data[0]); // Size Update to 20000 => 20000 - 31 = 19969 Assert.Equal(0x81, data[1]); // 19969 % 128 + 128 = 0x81, 19969 / 128 = 156 Assert.Equal(0x9c, data[2]); // 156 % 128 + 128 = 0x9c, 156 / 128 = 1 Assert.Equal(0x01, data[3]); // 1 Assert.Equal(0x88, data[4]); // :status 200 }
/// <summary> /// Test SemaphoreSlim Wait and Release methods concurrently /// </summary> /// <param name="initial">The initial semaphore count</param> /// <param name="maximum">The maximum semaphore count</param> /// <param name="waitThreads">Number of the threads that call Wait method</param> /// <param name="releaseThreads">Number of the threads that call Release method</param> /// <param name="succeededWait">Number of succeeded wait threads</param> /// <param name="failedWait">Number of failed wait threads</param> /// <param name="finalCount">The final semaphore count</param> /// <returns>True if the test succeeded, false otherwise</returns> private static void RunSemaphoreSlimTest8_ConcWaitAndRelease(int initial, int maximum, int waitThreads, int releaseThreads, int succeededWait, int failedWait, int finalCount, int timeout) { SemaphoreSlim semaphore = new SemaphoreSlim(initial, maximum); Task[] threads = new Task[waitThreads + releaseThreads]; int succeeded = 0; int failed = 0; ManualResetEvent mre = new ManualResetEvent(false); // launch threads for (int i = 0; i < threads.Length; i++) { if (i < waitThreads) { // We are creating the Task using TaskCreationOptions.LongRunning to // force usage of another thread (which will be the case on the default scheduler // with its current implementation). Without this, the release tasks will likely get // queued behind the wait tasks in the pool, making it very likely that the wait tasks // will starve the very tasks that when run would unblock them. threads[i] = new Task(delegate () { mre.WaitOne(); if (semaphore.Wait(timeout)) { Interlocked.Increment(ref succeeded); } else { Interlocked.Increment(ref failed); } }, TaskCreationOptions.LongRunning); } else { threads[i] = new Task(delegate () { mre.WaitOne(); semaphore.Release(); }); } threads[i].Start(TaskScheduler.Default); } mre.Set(); //wait work to be done; Task.WaitAll(threads); //check the number of succeeded and failed wait Assert.Equal(succeededWait, succeeded); Assert.Equal(failedWait, failed); Assert.Equal(finalCount, semaphore.CurrentCount); }
public FakeSynchronizationService() { _semaphore = new SemaphoreSlim(1); _syncs = new Dictionary <string, SemaphoreSlim>(); }
private static void TestConcurrentWaitAndWaitAsync(int syncWaiters, int asyncWaiters) { int totalWaiters = syncWaiters + asyncWaiters; var semaphore = new SemaphoreSlim(0); Task[] tasks = new Task[totalWaiters]; const int ITERS = 10; int randSeed = (int)DateTime.Now.Ticks; for (int i = 0; i < syncWaiters; i++) { tasks[i] = Task.Run(delegate { //Random rand = new Random(Interlocked.Increment(ref randSeed)); for (int iter = 0; iter < ITERS; iter++) { semaphore.Wait(); semaphore.Release(); } }); } for (int i = syncWaiters; i < totalWaiters; i++) { tasks[i] = Task.Run(async delegate { //Random rand = new Random(Interlocked.Increment(ref randSeed)); for (int iter = 0; iter < ITERS; iter++) { await semaphore.WaitAsync(); semaphore.Release(); } }); } semaphore.Release(totalWaiters / 2); Task.WaitAll(tasks); }
/// <summary> /// Initializes a <see cref="RateGate"/> with a rate of <paramref name="occurrences"/> /// per <paramref name="timeUnit"/>. /// </summary> /// <param name="occurrences">Number of occurrences allowed per unit of time.</param> /// <param name="timeUnit">Length of the time unit.</param> /// <exception cref="ArgumentOutOfRangeException"> /// If <paramref name="occurrences"/> or <paramref name="timeUnit"/> is negative. /// </exception> public RateGate(int occurrences, TimeSpan timeUnit) { // Check the arguments. if (occurrences <= 0) throw new ArgumentOutOfRangeException("occurrences", "Number of occurrences must be a positive integer"); if (timeUnit != timeUnit.Duration()) throw new ArgumentOutOfRangeException("timeUnit", "Time unit must be a positive span of time"); if (timeUnit >= TimeSpan.FromMilliseconds(UInt32.MaxValue)) throw new ArgumentOutOfRangeException("timeUnit", "Time unit must be less than 2^32 milliseconds"); Occurrences = occurrences; TimeUnitMilliseconds = (int)timeUnit.TotalMilliseconds; // Create the semaphore, with the number of occurrences as the maximum count. _semaphore = new SemaphoreSlim(Occurrences, Occurrences); // Create a queue to hold the semaphore exit times. _exitTimes = new ConcurrentQueue<int>(); // Create a timer to exit the semaphore. Use the time unit as the original // interval length because that's the earliest we will need to exit the semaphore. _exitTimer = new Timer(ExitTimerCallback, null, TimeUnitMilliseconds, -1); }