diff --git a/FiftyOne.Pipeline.CloudRequestEngine/FailHandling/AsyncLazyFailable.cs b/FiftyOne.Pipeline.CloudRequestEngine/FailHandling/AsyncLazyFailable.cs index b17cc448..0ac18bb4 100644 --- a/FiftyOne.Pipeline.CloudRequestEngine/FailHandling/AsyncLazyFailable.cs +++ b/FiftyOne.Pipeline.CloudRequestEngine/FailHandling/AsyncLazyFailable.cs @@ -31,6 +31,7 @@ public class AsyncLazyFailable private readonly Func _mainFunc; private readonly object _taskLock = new object(); private Task _activeTask; + private Task _errorHandlingTask; private TResult _result; // volatile: @@ -90,41 +91,49 @@ public async Task GetValueAsync(CancellationToken token) private Task GetOrBuildActiveTask() { - Task createdTask; lock (_taskLock) { if (_activeTask is object) // i.e. is not null { return _activeTask; } - createdTask = _activeTask = Task.Run(TryGetNewValue); + _activeTask = Task.Run(_mainFunc); + _errorHandlingTask = ConsumeActiveTaskFailure(_activeTask); + return _activeTask; } - _ = WatchForActiveTaskFailure(createdTask); // fire and forget - return createdTask; } private TResult TryGetNewValue() { - _result = _mainFunc(); + try + { + _result = _mainFunc(); - // volatile write, can’t be reordered with prior operations - _hasResult = true; + // volatile write, can’t be reordered with prior operations + _hasResult = true; - return _result; + return _result; + } + catch + { + lock (_taskLock) + { + _activeTask = null; + _errorHandlingTask = null; + } + throw; + } } - private async Task WatchForActiveTaskFailure(Task mainTask) + private async Task ConsumeActiveTaskFailure(Task mainTask) { try { - await mainTask; + _ = await mainTask; } catch { - lock (_taskLock) - { - _activeTask = null; - } + // nop -- just consume the failure } } }