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