1

I'm using the Polly library to monitor/restart tasks in C#. I've got a bit of "dumb" sample code to test out the restart mechanism.

I've noticed that my await Task.WhenAll(policy_list.ToArray()); doesn't always await policies all the time. Instead, this just gets passed through immediately.

What is the proper method for an "infinite" await such that Polly keeps monitoring my tasks?

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;

            }
        }
    }
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Izzo
  • 4,461
  • 13
  • 45
  • 82
  • 1
    I can't replicate the behavior you're seeing, for me it just runs forever awaiting, the only thing I noticed is that you should capture the `i` into it's own inner scope var, `var j = i` and pass that as `task_id` so it doesn't get stuck at 2 for all your tasks – JSteward Jan 10 '20 at 21:35
  • I can't replicate the issue either. Also take a look at this: [Captured variable in a loop in C#](https://stackoverflow.com/questions/271440/captured-variable-in-a-loop-in-c-sharp) – Theodor Zoulias Jun 19 '20 at 12:52

1 Answers1

0
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}

with this function you can await and process each task after return some value in a parallels execution, if use just Task.WhenAll only you will be able to log results after completion of all tasks!

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);
emdlab
  • 11
  • 2