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.

+3


source share


2 answers


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

+2


source


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);
}

      

+1


source







All Articles