继续执行<t>任务<you>而不阻止结果</u> </t>

时间:2012-08-14 15:37:53

标签: .net asynchronous

我有两个异步方法Task<int> DoInt()Task<string> DoString(int value)。我有第三个异步方法Task<string> DoBoth(int value),其目标是异步执行DoInt(),将其输出汇总到DoString(int)并使结果为DoBoth()的结果。

重要的限制是:

  1. 我可能没有DoInt()DoString()的源代码,所以我不能 修改它们。
  2. 我不想在任何时候阻止
  3. 必须将一个任务的输出(结果)作为输入传递给下一个
  4. 最终输出(结果)是我想成为DoBoth()
  5. 的结果

    关键是我已经拥有异步的方法(即返回任务),我希望将数据从任务传递到任务,而不会阻塞,在最初的任务中返回最终结果。除了以下代码中没有阻塞之外,我可以执行以下所有操作:

    代码示例:

    // Two asynchronous methods from another library, i.e. can't be changed
    Task<int> DoInt(); 
    Task<string> DoString(int value);
    
    Task<string> DoBoth()
    {
        return DoInt().ContinueWith<string>(intTask => 
        {
            // Don't want to block here on DoString().Result
            return DoString(intTask.Result).Result; 
        });
    }
    

    由于Task<string> DoString(int)已经是一个异步方法,我该如何干净地创建一个非阻塞的延续?实际上,我想从现有的Task创建一个延续,而不是从Func。

    创建

2 个答案:

答案 0 :(得分:8)

您可以使用TaskExtensions.Unwrap编写整个链:

Task<string> DoBoth(int value)
{
    Task<Task<string>> task = DoInt(value).ContinueWith(valueTask => 
    {
        return DoString(valueTask.Result); 
    });

    return task.Unwrap();
}

请注意,这假设DoInt定义为Task<int> DoInt(int value);,与您的描述不同,但请遵循您的代码示例。

如果DoInt不接受int参数(与您的声明匹配),则可能会变为:

Task<string> DoBoth()
{
    return DoInt().ContinueWith(t => DoString(t.Result)).Unwrap();
}

作为额外的 - 使用C#5和.NET 4.5(或异步目标包),您可以将其写为:

async Task<string> DoBoth(int value)
{
    int first = await DoInt(value);
    return await DoString(first);
}

答案 1 :(得分:0)