延迟和递归
Delay and recurse
我正在尝试编写一个函数来测试某些条件和 return 一个值,但如果不满足条件,它会等待,然后重试。当然,我可以只输入一个 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);
它可以编译,但这似乎也不完全正确。
因为你希望你的方法是异步的,当你想得到一个 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
已经在完成将您的 Task<Task<T>>
变成 Task<T>
.
当然,在大多数情况下,您通常不应该在 async
方法中使用 ContinueWith
,您应该简单地使用 await
将延续附加到您的任务:
await Task.Delay(waittime)
return Get<T>(waitime);
同样值得注意的是,你真的应该在这里使用 while
循环,而不是使用递归,特别是因为你有一个 async
方法,这意味着构建 另一个 每个递归调用的状态机。
我正在尝试编写一个函数来测试某些条件和 return 一个值,但如果不满足条件,它会等待,然后重试。当然,我可以只输入一个 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);
它可以编译,但这似乎也不完全正确。
因为你希望你的方法是异步的,当你想得到一个 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
已经在完成将您的 Task<Task<T>>
变成 Task<T>
.
当然,在大多数情况下,您通常不应该在 async
方法中使用 ContinueWith
,您应该简单地使用 await
将延续附加到您的任务:
await Task.Delay(waittime)
return Get<T>(waitime);
同样值得注意的是,你真的应该在这里使用 while
循环,而不是使用递归,特别是因为你有一个 async
方法,这意味着构建 另一个 每个递归调用的状态机。