【发布时间】:2015-08-26 07:41:19
【问题描述】:
我想实现一个重试任务,它采用之前失败的任务操作并重复它。
这是我目前所拥有的。然而,它只是重复了任务出错的事实,而不是实际再次触发任务的操作。
public static async Task<T> Retry<T>(this Task<T> task, int retryCount, int delay, TaskCompletionSource<T> tcs = null)
{
if (tcs == null)
{
tcs = new TaskCompletionSource<T>();
}
await task.ContinueWith(async _original =>
{
if (_original.IsFaulted)
{
if (retryCount == 0)
{
tcs.SetException(_original.Exception.InnerExceptions);
}
else
{
Console.WriteLine("Unhandled exception. Retrying...");
await Task.Delay(delay).ContinueWith(async t =>
{
await Retry(task, retryCount - 1, delay, tcs);
});
}
}
else
tcs.SetResult(_original.Result);
});
return await tcs.Task;
}
我试图通过一点反思来获得行动。但是,似乎一旦任务完成,操作就会设置为 null。
var action = task
.GetType()
.GetField("m_action", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(task) as Action;
理想情况下,我希望我的实现如下所示:
try
{
await MakeFailure().Retry(5, 1000);
}
catch (Exception ex)
{
Console.WriteLine("I had an exception");
}
这可能是不可能的,但我想在将代码重构为Retry(Func<T> task)之前确定一下
【问题讨论】:
-
您是否反对不将此作为扩展方法并将方法签名更改为
static async Task<T> Retry<T>(Func<Task<T>> taskFactory, int retryCount, ...? -
不完全反对。但它将代码流更改为故障优先布局,我不喜欢
Retry(async () => await MakeFailure(),5,1000)不如await MakeFailure().Retry(5,1000)干净 -
不要试图破解 TPL 来做一些不该做的事情。在它上面创建一个抽象。