我正在使用 Polly 库在 C# 中监视/重新启动任务。我有一些"愚蠢"的示例代码来测试重启机制。
我注意到我的await Task.WhenAll(policy_list.ToArray());
并不总是一直等待政策。相反,这只会立即通过。
"无限"等待的正确方法是什么,以便 Polly 继续监视我的任务?
using System;
using System.IO;
using System.Collections.Generic;
using Polly;
using System.Threading.Tasks;
namespace Sampler
{
class Program
{
public static async Task Main(string[] args)
{
// create and execute policies for each sampler
List<Task> policy_list = new List<Task>();
for(int i = 0; i < 2; i++)
{
var policy = Policy
.Handle<Exception>()
.RetryForeverAsync()
.ExecuteAsync(async () => await Program.TaskMethod(i.ToString()));
policy_list.Add(policy);
}
await Task.WhenAll(policy_list.ToArray());
Console.WriteLine("Press any key to exit...");
Console.ReadLine();
}
public static async Task TaskMethod(string task_id)
{
Console.WriteLine("Starting Task {0}", task_id);
while (true)
{
await Task.Delay(5000);
Console.WriteLine("Hello from task {0}", task_id);
int i = 0;
int b = 32 / i;
}
}
}
}
public async Task AwaitAndProcessAsync<T>(Task<T> task) where T : PolicyResult<ExecutionResult>
{
var result = await task;
if (result.Outcome == OutcomeType.Failure)
{
var android = result.Context.Values.OfType<AndroidTestHelper>().First();
if (result.FinalException != null)
{
LogsHelper.iLog.Fatal($"{result.Context.First().Key} failed after too many retries!");
}
}
}
//where ExecutionResult : enum {PASSED, FAILED}
使用此函数,您可以在 Parallels 执行中返回一些值后等待和处理每个任务,如果只使用Task.WhenAll
您将能够在所有任务完成后记录结果!
var list = await GenerateSomeDevices(20);
var tasks = new List<Task<PolicyResult<ExecutionResult>>>();
foreach (var device in list)
{
var android = new AndroidTestHelper(device);
var t = bulkHeadPolicy.ExecuteAndCaptureAsync(async (context, _token) =>
{
LogsHelper.iLog.Debug($"[{device.Index}] start testing..");
return await android.TestDriver(_token);
}, new Dictionary<string, object>() { { $"[{device.Index}] Process", android } }, cancellationToken);
tasks.Add(t);
await Task.Delay(10000);
}
var processingTasks = tasks.Select(AwaitAndProcessAsync).ToList();
await Task.WhenAll(processingTasks).ContinueWith((task) =>
{
if (task.IsCompleted)
LogsHelper.iLog.Information("DONE");
}, cancelationToken);