public void ShouldOnlyRunOnceWhenInvokeConcurrent() { var key = Utility.NewPassword(); var isFirstTime = true; var actionExecutionCount = 0; var locker = new object(); var locker2 = new object(); Mock.Get(lockService).Setup(p => p.Lock(key, key, It.IsAny <TimeSpan>())) .ReturnsAsync(() => { lock (locker) { var isFirst = isFirstTime; isFirstTime = false; return(isFirst); } }); var tasks = System.Linq.Enumerable.Range(0, 10).Select(p => lockService.GlobalRunOnce(key, Action)).ToArray(); Task.WaitAll(tasks); int executeActionTaskCount = tasks.Count(p => p.Result); Assert.AreEqual(1, executeActionTaskCount); Assert.AreEqual(1, actionExecutionCount); void Action() { lock (locker2) { Task.Delay(10).Wait(); actionExecutionCount++; } } }
public static async Task GlobalRunOnceOrWaitFor(this ILockService lockService, string key, Action action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var executed = await lockService.GlobalRunOnce(key, action); if (executed == false) { await lockService.WaitFor(key); } }