gpt4 book ai didi

c# - 使用任务重试异步函数——哪种方法更有效?

转载 作者:太空狗 更新时间:2023-10-29 23:14:57 26 4
gpt4 key购买 nike

我想知道一般来说哪种方法在内存和资源使用方面更有效。

特别是方法 #1,我很难想象将如何创建任务对象和启动线程?顺便说一句,有人可以详细解释幕后发生的事情吗?

如果两者之间没有区别(希望避免冒泡异步),我想使用#1。对于#2,我知道编译器将在下面生成一个状态机并返回。 OTOH,#1 在概念上似乎是递归的,但它在传统意义上是递归的,就像在一个等待另一个的堆栈框架中一样吗?

方法一:

internal static Task ExecuteAsyncWithRetry(Func<Task> methodToExecute, Func<bool> shouldRetry)
{
var tcs = new TaskCompletionSource<object>();

try
{
return methodToExecute().ContinueWith<Task>((t) =>
{
if (t.IsFaulted || t.IsCanceled)
{
if (shouldRetry())
{
return ExecuteAsyncWithRetry(methodToExecute, shouldRetry);
}
else
{
tcs.SetException(t.Exception);
}
}
else
{
tcs.SetResult(null);

}

return tcs.Task;
}, TaskContinuationOptions.ExecuteSynchronously).Unwrap();
}
catch(Exception ex)
{
tcs.SetException(ex);
}

return tcs.Task;
}

方法#2(忽略两者之间异常传播的差异):

internal static async Task ExecuteWithRetry(Func<Task> methodToExecute, Func<bool> shouldRetry)
{
while (true)
{
try
{
await methodToExecute();
}
catch(Exception ex)
{
if(!shouldRetry())
{
throw;
}
}
}
}

最佳答案

除了不同的异常和取消传播之外,还有另一个主要区别。

在第一种情况下,由于 TaskContinuationOptions.ExecuteSynchronously,您的延续在任务已完成的同一线程上运行。

在第二种情况下,它将在原始同步上下文中运行(如果 methodToExecute 是在具有同步上下文的线程上调用的)。

尽管第一种方法可能更有效,但它也可能难以理解(尤其是当您或其他人在一年后再次使用它时)。

我会关注 KISS principle并坚持第二个,有一个修改:

await methodToExecute().ConfigureAwait(false);

已更新以解决评论:

"OTOH, #1 seems recursive conceptually but will it be recursive in the traditional sense as in one stack-frame waiting on the other?"

对于 #1,它是在同一堆栈帧上递归发生,还是在不同堆栈帧上异步发生,完全取决于 methodToExecute 中发生的事情。在大多数情况下,如果您在 methodToExecute 中使用一些自然的异步 API,则不会有传统的递归。例如,HttpClient.GetStringAsync completes on a random IOCP pool thread ,并且 Task.Delay 在随机工作池线程上完成。

但是,即使是异步 API 也可能在同一个线程上同步完成(例如 MemoryStream.ReadAsyncTask.Delay(0)),在这种情况下会有递归。

或者,在 methodToExecute 中使用 TaskCompletionSource.SetResult 也可能触发同步延续。

如果你真的想避免任何递归的可能性,通过 Task.Run (或 Task.Factory.StartNew/Task.Unwrap)。或者,更好的是,删除 TaskContinuationOptions.ExecuteSynchronously

对于#2,同样的场景也是可能的,即使初始线程上有同步上下文。

关于c# - 使用任务重试异步函数——哪种方法更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22725125/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com