Creating a method to return Task <List <MyDataObject>> foo ()
I can solve this in .Net 4.5, but I have to solve it in .NET 4.0 and so far I have not been successful. I have not been able to get answers for Task<List<MyDataObject>>
. The code below can create List<MyDataObject>
.
public Task<List<MyDataObject>> Foo() { IEnumerable<string> names = GetList(); var tasks = new List<Task>(); foreach (var name in names) { tasks.Add(Task<MyDataObject>.Factory.StartNew( () => { var reply = new MyDataObject(); var workerObject = new WorkerObject(); workerObject.Foo2(); reply.Success = true; return reply; })); } Task.WaitAll(tasks.ToArray()); var replyList = new List<MyDataObject>(); for (int i = 0; i < tasks.Count(); i++) { replyList.Add(((Task<MyDataObject>)tasks[i]).Result); } return replyList; }
WhenAll()
- only 4.5
await
- only 4.5
so i can't accept these
I agree that this won't compile. I have shown that I can repeat the results. However, I don't know how to go from
List<MyDataObject>()
to
Task<List<MyDataObject>>
Thanks for answers. I am going to accept Yuval Itschakov, because he solves my problem in a simple way. I'm not limited to new builds for this use case. I would choose option 280Z28 second if I had another method that requires this feature.
source share
Use TaskCompletionSource<List<MyDataObject>>
Task.WaitAll(tasks.ToArray()); var replyList = new List<MyDataObject>(); for (int i = 0; i < tasks.Count(); i++) { replyList.Add(((Task<MyDataObject>)tasks[i]).Result); } var tcs = new TaskCompletionSource<List<MyDataObject>>(); tcs.SetResult(replyList); return tcs.Task;
You can also download Microsoft.Bcl.Async
to get Effect NET 4.5 in .NET 4.0
source share
In .NET 4.0, you get exactly the same behavior if you follow these steps:
Define a method WhenAll
public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks) { TaskCompletionSource<TResult[]> taskCompletionSource = new TaskCompletionSource<TResult[]>(); Action<Task<TResult>[]> continuationAction = completedTasks => { List<TResult> results = new List<TResult>(); List<Exception> exceptions = new List<Exception>(); bool canceled = false; foreach (var completedTask in completedTasks) { switch (completedTask.Status) { case TaskStatus.RanToCompletion: results.Add(completedTask.Result); break; case TaskStatus.Canceled: canceled = true; break; case TaskStatus.Faulted: exceptions.AddRange(completedTask.Exception.InnerExceptions); break; default: throw new InvalidOperationException("Unreachable"); } } if (exceptions.Count > 0) taskCompletionSource.SetException(exceptions); else if (canceled) taskCompletionSource.SetCanceled(); else taskCompletionSource.SetResult(results.ToArray()); }; Task.Factory.ContinueWhenAll(tasks.ToArray(), continuationAction); return taskCompletionSource.Task; }
Use a method Select
from the Rackspace Thread Library to return expected results
public Task<List<MyDataObject>> Foo() { IEnumerable<string> names = GetList(); var tasks = new List<Task<MyDataObject>>(); foreach (var name in names) { tasks.Add(Task<MyDataObject>.Factory.StartNew( () => { var reply = new MyDataObject(); var workerObject = new WorkerObject(); workerObject.Foo2(); reply.Success = true; return reply; })); } return WhenAll(tasks).Select(result => new List<MyDataObject>(result.Result)); }
As an alternative:
Alternatively, you can change the method WhenAll
above to return Task<List<TResult>>
instead Task<TResult[]>
. This will allow you to simply use the following method.
public Task<List<MyDataObject>> Foo() { IEnumerable<string> names = GetList(); var tasks = new List<Task<MyDataObject>>(); foreach (var name in names) { tasks.Add(Task<MyDataObject>.Factory.StartNew( () => { var reply = new MyDataObject(); var workerObject = new WorkerObject(); workerObject.Foo2(); reply.Success = true; return reply; })); } return WhenAll(tasks); }
source share