如何在不知道第一个任务的结果类型的情况下将任务链接到另一个任务

时间:2011-08-16 18:49:01

标签: generics reflection expression-trees task-parallel-library

假设我有一个将Task作为对象返回的API:

    private static object CreateTask()
    {
        return Task.Factory.StartNew(() => "Task string");
    }

我需要使用一个函数扩展API,该函数返回另一个链接到CreateTask函数返回的Task的Task,以便新Task的结果将是初始Task的结果。即像这样的东西:

    private static object WrapTask(dynamic task)
    {
        object new_task = task.ContinueWith(parentTask => parentTask.Result, TaskContinuationOptions.ExecuteSynchronously);

        return new_task;
    }

使用示例:

        var task = (Task<string>)WrapTask(CreateTask());

        Console.WriteLine(task.Result);

应该打印“任务字符串”字符串。

WrapTask函数的问题在于编译器拒绝接受这种结构:

        object result = task.ContinueWith(parentTask => parentTask.Result, TaskContinuationOptions.ExecuteSynchronously);

出现以下错误:

        Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type

非常感谢有关如何以所述方式扩展API的任何想法。

1 个答案:

答案 0 :(得分:2)

您可以使用动态类型来调用动态类型提供的类型推断的泛型方法:

private static object WrapTask(dynamic task)
{
    return WrapTaskImpl(task);
}

private static Task<T> WrapTaskImpl<T>(Task<T> task)
{
    return task.ContinueWith(parentTask => parentTask.Result,
        TaskContinuationOptions.ExecuteSynchronously);
}

根本不清楚这种包装的重点是什么,请注意......以及为什么你只想施放WrapTask结果 - 如果你知道的话这是一个任务,为什么不转换CreateTask的结果,此时你可以简单地调用WrapTask?或者也许让WrapTask执行演员表演?

private static Task<T> WrapTask<T>(object task)
{
    Task<T> realTask = (Task<T>) task;
    return realTask.ContinueWith(parentTask => parentTask.Result, 
                                 TaskContinuationOptions.ExecuteSynchronously);
}

然后您的主叫代码变为

var task = WrapTask<string>(CreateTask());

Console.WriteLine(task.Result);