【问题标题】:Creating a method to return Task<List<MyDataObject>> foo()创建一个返回 Task<List<MyDataObject>> foo() 的方法
【发布时间】:2014-09-27 06:30:29
【问题描述】:

我可以在 .Net 4.5 中解决这个问题,但我必须在 .Net 4.0 中解决它,到目前为止我还没有成功。 我无法将我的回复发送到Task&lt;List&lt;MyDataObject&gt;&gt;。下面的代码可以创建List&lt;MyDataObject&gt;。

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() 仅 4.5

await 仅 4.5

所以我不能接受那些

我同意这不会编译。我展示的是我可以遍历结果。但是我不知道如何从

List<MyDataObject>()

到

Task<List<MyDataObject>>

感谢您的回复。我将接受 Yuval Itzchakov 的回答,因为它以简单的方式解决了我的问题。对于这个用例,我仅限于没有新的程序集。如果我有另一种需要此功能的方法,我会选择 280Z28 的第二个选项。

【问题讨论】:

  • 你的函数应该返回一个Task&lt;List&lt;MyDataObject&gt;&gt;,但你返回一个List&lt;MyDataObject&gt;。在不知道 Tasks 的情况下,这对我来说似乎是一个编译时问题。
  • 另外,so far I have not been successful 是什么意思?什么不工作?请告诉我们具体情况。
  • 最好使用async/await。但如果没有这个选项,试试这个:Creating a completed task

标签: c# task-parallel-library


【解决方案1】:

使用TaskCompletionSource&lt;List&lt;MyDataObject&gt;&gt;

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;

您也可以下载Microsoft.Bcl.Async获取 .NET 4.0 中的 NET 4.5 效果

【讨论】:

  • 请注意,要在 .NET 4.0 中使用 Microsoft.Blc.Async,您需要安装 KB2468871(.NET Framework 4 的更新)
【解决方案2】:

如果您按照以下步骤操作,您将在 .NET 4.0 中获得完全相同的行为:

定义一个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;
}

使用Rackspace Threading Library 中的Select 方法返回预期结果

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

或者:

作为替代方案,您可以修改上面的WhenAll 方法以返回Task&lt;List&lt;TResult&gt;&gt; 而不是Task&lt;TResult[]&gt;。这将允许您简单地使用以下方法。

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

【讨论】:

    猜你喜欢
    • 2016-09-23
    • 2015-05-20
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    相关资源
    最近更新 更多