Adding more data to a result of a task
Every now and then I need to generate , from an array of data, an array of Tasks and then
await Task.WhenAll(TheTaskArray)
The problem is that I need to consolidate the return data of each array with the original array – to make some modifications.
For example, in the generator of https://ignatandrei.github.io/RSCG_Examples/v2/docs/category/rscg-examples I do something like this
var t = _AllDescriptions .Select(it =>GrabReadMe(it)) .ToArray(); var data = await Task.WhenAll(t); //now, for each item in data array I want to put something into original _AllDescriptions
My first try was a simple class
public struct TaskWithData<TData, TResult>//: INotifyCompletion { private readonly TData data; private readonly Task<TResult> taskToExecute; public TaskWithData(TData data,Task<TResult> taskToExecute) { ArgumentNullException.ThrowIfNull(taskToExecute); this.data = data; this.taskToExecute = taskToExecute; } # region add this to have Task.WhenAll public async Task<( TData data, TResult res)> GetTask() { var res = await taskToExecute; return (data,res); } public static explicit operator Task<(TData data, TResult res)>(TaskWithData<TData,TResult> b) => b.GetTask() ; #endregion }
And now the code could be written as
var t = _AllDescriptions.Select( it => new TaskWithData<Description, string?>(it, GrabReadMe(it)) ) .Select(td=>td.GetTask()) .ToArray(); var desc = await Task.WhenAll(t); foreach (var item in desc) { item.data.Readme = item.res; }
But I do not like so much … so 2 iterations with extensions
public static class Extensions { #region transform to task public static Task<( TData data, TResult res)> AddData<TData, TResult>(this Task<TResult> taskToExecute, TData data) { var td=new TaskWithData<TData, TResult>(data,taskToExecute); return td.GetTask(); } public static Task<(TData data, TResult res)>[] SelectTaskWithData<TData, TResult>(this TData[] arr,Func<TData, Task<TResult>> func) { return arr.Select(it => func(it).AddData(it)).ToArray(); } #endregion }
So now the code becomes
var t = _AllDescriptions .Select(it =>GrabReadMe(it).AddData(it)) .ToArray();
or
var t = _AllDescriptions.SelectTaskWithData(GrabReadMe).ToArray();
It was interesting to create this in order to add more data to the return value of a Task
Leave a Reply