延迟和递归

时间:2015-08-26 14:21:16

标签: c# task

我试图编写一个测试某些条件并返回值的函数,但如果条件不满意,它会等待然后再试一次。当然,我可以投入一个Thread.Sleep,但我认为我应该能够通过任务asynch / await来解决这个问题,但我无法做到非常合适的语法使这项工作。例如:

public async Task<T> Get<T>(TimeSpan waittime)
{
    if (someCondition) 
    {
        return SomeFunctionThatReturnsValue<T>();
    }
    else
    {
        return await Get<T>(waitime);
    }
}

有效,但没有任何延迟(显然),所以我尝试过多种变体:

public async Task<T> Get<T>(TimeSpan waittime)
{
    if (someCondition) 
    {
        return SomeFunctionThatReturnsValue<T>();
    }
    else
    {
        return await Task.Delay(waittime).ContinueWith(t => Get<T>(waitime));
    }
}

但是这给了我编译时错误:

Error 52 Since this is an async method, the return expression must be of type 'T' rather than 'Task<T>'

我可以将最后return更改为:

return await Task.Delay(waittime).ContinueWith(t => Get<T>(waittime).Result);

它编译,但这似乎也不正确。

1 个答案:

答案 0 :(得分:4)

由于您希望您的方法是异步的,当您想要获得Task的结果时,您应该使用await,而不是Result,以便异步执行操作,所以你可以把这个操作写成:

return await await Task.Delay(waittime).ContinueWith(t => Get<T>(waitime));

或者,只要您有两个等待,您就可以使用Unwrap;它并不是真的好或坏;它的等价物:

return await Task.Delay(waittime).ContinueWith(t => Get<T>(waitime)).Unwrap();

请注意,通过使用Unwrap,您还可以使该方法不是async而不是await,因为Unwrap已经在完成转换{{1}进入Task<Task<T>>

当然,在大多数情况下,您通常不应该在Task<T>方法中使用ContinueWith,您应该只使用async为您的任务添加延续:

await

还值得注意的是,你应该在这里使用await Task.Delay(waittime) return Get<T>(waitime); 循环,而不是使用递归,特别是因为你有一个while方法,这意味着构建另一个< / em>每个递归调用的状态机。