public async Task ShouldNotRepeatTasks() { //Arrange var logs = new List <Log>(); var numTasksRunning = 0; var taskCompletions = Enumerable .Range(start: 1, count: 10) .Select(i => new TaskCompletionSource <int>()) .ToList(); Func <int, Task> addLog = async taskId => { numTasksRunning++; logs.Add(new Log { Id = taskId, NumTasksRunning = numTasksRunning }); await taskCompletions[taskId - 1].Task; numTasksRunning--; }; var tasks = new List <Func <Task> > { async() => await addLog(3), async() => await addLog(2), async() => await addLog(7), async() => await addLog(4), async() => await addLog(1), async() => await addLog(5), async() => await addLog(8), async() => await addLog(9), async() => await addLog(6), async() => await addLog(10) }; //Act int maxConcurrency = 3; var whenAllComplete = ConcurrentTask.WhenAll(tasks, maxConcurrency); taskCompletions.ForEach(taskCompletion => taskCompletion.SetResult(0)); await whenAllComplete; //Assert var repeats = logs .Select(log => new { Id = log.Id, Count = logs.Count(l => l.Id == log.Id) }) .Where(result => result.Count > 1) .ToList(); repeats.Count.Should().Be(0, because: $"there should be no repeats but: {string.Join(", ", repeats.Select(repeat => $"(Id: {repeat.Id}, Count: {repeat.Count})"))}."); }
public async Task ShouldLimitConcurrency() { //Arrange var logs = new List <Log>(); var numTasksRunning = 0; var taskCompletions = Enumerable .Range(start: 1, count: 10) .Select(i => new TaskCompletionSource <int>()) .ToList(); Func <int, Task> addLog = async taskId => { numTasksRunning++; logs.Add(new Log { Id = taskId, NumTasksRunning = numTasksRunning }); await taskCompletions[taskId - 1].Task; numTasksRunning--; }; var tasks = new List <Func <Task> > { async() => await addLog(1), async() => await addLog(4), async() => await addLog(6), async() => await addLog(3), async() => await addLog(5), async() => await addLog(7), async() => await addLog(2), async() => await addLog(9), async() => await addLog(10), async() => await addLog(8) }; //Act int maxConcurrency = 3; var whenAllComplete = ConcurrentTask.WhenAll(tasks, maxConcurrency); taskCompletions.ForEach(taskCompletion => taskCompletion.SetResult(0)); await whenAllComplete; //Assert logs .Max(log => log.NumTasksRunning) .Should() .Be(maxConcurrency, because: $"there should be up to {maxConcurrency} tasks in flight."); }
public async Task ShouldLimitConcurrency() { //Arrange var numTasksRunning = 0; var taskCompletions = Enumerable .Range(start: 1, count: 10) .Select(i => new TaskCompletionSource <int>()) .ToList(); Func <int, Task <int> > resultFromTaskId = async taskId => { numTasksRunning++; var taskCount = numTasksRunning; await taskCompletions[taskId - 1].Task; numTasksRunning--; return(taskCount); }; var tasks = new List <Func <Task <int> > > { async() => await resultFromTaskId(1), async() => await resultFromTaskId(4), async() => await resultFromTaskId(6), async() => await resultFromTaskId(3), async() => await resultFromTaskId(5), async() => await resultFromTaskId(7), async() => await resultFromTaskId(2), async() => await resultFromTaskId(9), async() => await resultFromTaskId(10), async() => await resultFromTaskId(8) }; //Act int maxConcurrency = 3; var getTaskCounts = ConcurrentTask.WhenAll(tasks, maxConcurrency); taskCompletions.ForEach(taskCompletion => taskCompletion.SetResult(0)); var taskCounts = await getTaskCounts; //Assert taskCounts.Max().Should().Be(maxConcurrency, because: $"there should be up to {maxConcurrency} tasks in flight."); }
public async Task ShouldRunAllTasks() { //Arrange var logs = new List <Log>(); Func <Log, Task> addLog = log => { logs.Add(log); return(Task.FromResult(0)); }; var tasks = new List <Func <Task> > { async() => await addLog(new Log { Id = 1 }), async() => await addLog(new Log { Id = 2 }), async() => await addLog(new Log { Id = 3 }), async() => await addLog(new Log { Id = 4 }), async() => await addLog(new Log { Id = 5 }) }; //Act await ConcurrentTask.WhenAll(tasks, maxConcurrency : 5); //Assert logs.Should().BeEquivalentTo(new List <Log> { new Log { Id = 1 }, new Log { Id = 2 }, new Log { Id = 3 }, new Log { Id = 4 }, new Log { Id = 5 }, }); }
public async Task ShouldReturnTasksInOrderDespiteWhenTheyResolve() { //Arrange var taskCompletions = Enumerable .Range(start: 1, count: 10) .Select(i => new TaskCompletionSource <int>()) .ToList(); Func <int, Task <int> > getResultFromTaskId = async taskId => { await taskCompletions[taskId - 1].Task; return(taskId); }; var tasks = Enumerable .Range(start: 1, count: 10) .Select(index => ((Func <Task <int> >)(async() => await getResultFromTaskId(index)))); //Act int maxConcurrency = 3; var getResults = ConcurrentTask.WhenAll(tasks, maxConcurrency); taskCompletions[4].SetResult(0); taskCompletions[1].SetResult(0); taskCompletions[0].SetResult(0); taskCompletions[9].SetResult(0); taskCompletions[2].SetResult(0); taskCompletions[6].SetResult(0); taskCompletions[8].SetResult(0); taskCompletions[3].SetResult(0); taskCompletions[7].SetResult(0); taskCompletions[5].SetResult(0); var results = await getResults; //Assert results.Should().BeEquivalentTo(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, ops => ops.WithStrictOrdering()); }
private static async Task <BitmapImage> GetOrPreCacheAsync(Uri uri, bool throwOnError, bool isPreCache) { ConcurrentTask task; string key = GetCacheFileName(uri); BitmapImage image = null; lock (_concurrentTasks) { if (_concurrentTasks.ContainsKey(key)) { task = _concurrentTasks[key]; } else { task = new ConcurrentTask() { Task = GetFromCacheOrDownloadAsync(uri, key, isPreCache), IsPreCache = isPreCache }; _concurrentTasks.Add(key, task); } } try { image = await task.Task; // if task was "PreCache task" and we needed "Get task" and task didnt return image we create new "Get task" and await on it. if (task.IsPreCache && !isPreCache && image == null) { lock (_concurrentTasks) { task = new ConcurrentTask() { Task = GetFromCacheOrDownloadAsync(uri, key, false), IsPreCache = isPreCache }; _concurrentTasks[key] = task; } image = await task.Task; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); if (throwOnError) { throw ex; } } finally { lock (_concurrencyLock) { if (_concurrentTasks.ContainsKey(key)) { _concurrentTasks.Remove(key); } } } return(image); }