Here is my approach. I have several IEventProviders,
interface IEventProvider
{
Task<Event> GetEvent();
}
Then I got a container class to wrap them, and keep calling and awaiting the GetEvent() to wait for next Event, e.g. socket async receiving, timer ticks, etc.
class EventProviderContainer : IEventProvider
{
private IEventProvider[] _providers;
private Task<Event>[] _tasks;
public EventProviderContainer(params IEventProvider[] providers)
{
_providers = providers;
}
public async Task<Event> GetEvent()
{
// Fill the _tasks first time we call the method.
if (_tasks == null)
_tasks = (from p in _providers select p.GetEvent()).ToArray();
Task<Event> task = await Task<Event>.WhenAny(_tasks);
// Get the provider index whose previous task is done.
int index = Array.IndexOf(_tasks, task);
// put next event of the provider into array.
_tasks[index] = _providers[index].GetEvent();
return await task;
}
}
I think it is a bit of ugly. Is it a better way to do it?
If you want one event for each provider at a time then I recommend you check out the Processing tasks as they complete MSDN article which includes an
Interleavedmethod. This method takes a collection of tasks and returns a new array of tasks that will yield in order of completion.On the other hand, if you want to continuously receive events from each provider as they arrive, then I recommend you look at the Reactive Extensions (Rx) project from Microsoft.
Using Rx, your event provider interface would become something like:
Your container provider would then use the Observable.Merge extension method to combine the events of each child provider.
To actually receive the events, you subscribe to the observable by attaching a callback delegate that’s executed each time a new event is available.
The above example uses a test event provider that returns a continuous stream of events at the given period in milliseconds using the Observable.Timer extension method.