Simon Lomax
Simon Lomax

Reputation: 8972

Using Polly to run async task with timeout

I have a simple task that I would like to run in the background. The task should simply attempt to move a file. This task could fail because the file is in use in another process.

I would like to retry this action for a specified period of time and then timeout if the file is still locked.

I read about Polly and thought this would be ideal for my needs.

The code will eventually be included in an ASP.NET app but I've created a small console app in an attempt to demonstrate what I'm trying to achieve.

This is my first attempt with Polly so I could be totally off the mark here, but as soon as I run the app in Visual Studio 2013 I get the following error:

An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll

Additional information: Please use asynchronous-defined policies when calling asynchronous ExecuteAsync (and similar) methods.

Here is the code:

class Program
    {
        static void Main(string[] args)
        {
            RunMyTask().GetAwaiter().GetResult();
        }

        private static async Task RunMyTask()
        {
            var timeoutPolicy = Policy.Timeout(TimeSpan.FromSeconds(20), TimeoutStrategy.Pessimistic, (context, span, arg3) => {});
            var policyResult = await timeoutPolicy.ExecuteAndCaptureAsync(async () =>
            {
                await Task.Run(() =>
                {
                    while (!MoveFiles())
                    {
                    }
                });
            });
            if (policyResult.Outcome == OutcomeType.Failure && policyResult.FinalException is TimeoutRejectedException)
            {
                Console.WriteLine("Operation Timed out");
            }
            else
            {
                Console.WriteLine("Operation succeeded!!!!!");
            }
        }

        private static bool MoveFiles()
        {
            try
            {
                var origFile = @"c:\temp\mydb.sqlite";
                var tempFile = @"c:\temp\mydb.sqlite.tmp";
                File.Move(origFile, tempFile);
                File.Move(tempFile, origFile);
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }

What am I doing wrong?

Upvotes: 2

Views: 3362

Answers (1)

JSteward
JSteward

Reputation: 7091

You need to use the async variant of Timeout as well as the async execute method. Polly has async variants of each policy so you need to go async all the way.

TimeoutPolicy timeoutPolicy = Policy
  .TimeoutAsync([int|TimeSpan|Func<TimeSpan> timeout]
                [, TimeoutStrategy.Optimistic|Pessimistic]
                [, Func<Context, TimeSpan, Task, Task> onTimeoutAsync])

From Timeout policy

Upvotes: 3

Related Questions