Skip to content

Instantly share code, notes, and snippets.

@tommasobertoni
Created July 19, 2019 21:37
Show Gist options
  • Save tommasobertoni/cdb967b6c0154b67c87a37300736e1c8 to your computer and use it in GitHub Desktop.
Save tommasobertoni/cdb967b6c0154b67c87a37300736e1c8 to your computer and use it in GitHub Desktop.
AsyncCollector usage example
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace App
{
class Program
{
static async Task Main(string[] args)
{
// Instance received from an external API.
var transport = await FetchFromWebAPIAsync();
// Integrate the received data with our values.
await IntegrateDataAsync(transport);
}
private static async Task IntegrateDataAsync(Transport transport)
{
var collector = new AsyncCollector();
collector.Register(async () => transport.Vehichle.Name = await GetVehichleNameAsync(transport.Vehichle.Id));
if (transport.Stops != null)
{
foreach (var s in transport.Stops)
collector.Register(async () => s.Description = await GetStopDescriptionAsync(s.Id));
}
await collector.WhenAll();
}
#region Other methods
private static Task<Transport> FetchFromWebAPIAsync()
{
var t = new Transport
{
Vehichle = new Vehichle { Id = "1234", Name = null },
Stops = new List<Stop>
{
new Stop { Id = "a1", Time = DateTime.Now.AddSeconds(1), Description = null },
new Stop { Id = "b2", Time = DateTime.Now.AddSeconds(5), Description = null },
new Stop { Id = "c3", Time = DateTime.Now.AddSeconds(9), Description = null },
}
};
return Task.FromResult(t);
}
private static Task<string> GetVehichleNameAsync(string vehicleId) => Task.FromResult($"A vehichle: {vehicleId}");
private static Task<string> GetStopDescriptionAsync(string stopId) => Task.FromResult($"A stop: {stopId}");
#endregion
#region Models
class Transport
{
public Vehichle Vehichle { get; set; }
public List<Stop> Stops { get; set; }
}
class Vehichle
{
public string Id { get; set; }
public string Name { get; set; }
}
class Stop
{
public string Id { get; set; }
public DateTime Time { get; set; }
public string Description { get; set; }
}
#endregion
#region Async collector
class AsyncCollector
{
public IReadOnlyList<Task> Tasks => _tasks.AsReadOnly();
private readonly List<Task> _tasks = new List<Task>();
public void Register(Func<Task> asyncDelegate) =>
this.Register(asyncDelegate, out _);
public void Register(Func<Task> asyncDelegate, out Task registeredTask)
{
registeredTask = asyncDelegate();
_tasks.Add(registeredTask);
}
public async Task WhenAll(bool clearAfterwards = true)
{
try
{
await Task.WhenAll(_tasks);
}
finally
{
if (clearAfterwards)
_tasks.Clear();
}
}
public void Clear() => _tasks.Clear();
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment