From 8366a4361706ffe0e063ec5353f6e9e78fcef6b4 Mon Sep 17 00:00:00 2001 From: xinchen Date: Fri, 8 Jun 2018 13:42:54 -0700 Subject: [PATCH] [#106] Unobserved exception was rethrown by the finalizer thread --- .../Amqp/FaultTolerantAmqpObject.cs | 5 ++ Microsoft.Azure.Amqp/Singleton.cs | 51 ++++++++++--------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Microsoft.Azure.Amqp/Amqp/FaultTolerantAmqpObject.cs b/Microsoft.Azure.Amqp/Amqp/FaultTolerantAmqpObject.cs index 39c678fe..b8562cab 100644 --- a/Microsoft.Azure.Amqp/Amqp/FaultTolerantAmqpObject.cs +++ b/Microsoft.Azure.Amqp/Amqp/FaultTolerantAmqpObject.cs @@ -41,6 +41,11 @@ public bool TryGetOpenedObject(out T openedAmqpObject) return openedAmqpObject != null; } + protected override bool IsValid(T value) + { + return value.State == AmqpObjectState.Opened; + } + protected override async Task OnCreateAsync(TimeSpan timeout) { T amqpObject = await this.createObjectAsync(timeout).ConfigureAwait(false); diff --git a/Microsoft.Azure.Amqp/Singleton.cs b/Microsoft.Azure.Amqp/Singleton.cs index 26e5dcf5..0c477ece 100644 --- a/Microsoft.Azure.Amqp/Singleton.cs +++ b/Microsoft.Azure.Amqp/Singleton.cs @@ -95,13 +95,30 @@ public async Task GetOrCreateAsync(TimeSpan timeout) if (this.TryGet(out tcs)) { - return await tcs.Task.ConfigureAwait(false); + TValue current = await tcs.Task.ConfigureAwait(false); + if (this.IsValid(current)) + { + return current; + } + + this.Invalidate(current); } tcs = new TaskCompletionSource(); if (this.TrySet(tcs)) { - this.CreateValue(tcs, timeoutHelper.RemainingTime()).Fork(); + try + { + TValue value = await this.OnCreateAsync(timeout).ConfigureAwait(false); + tcs.SetResult(value); + } + catch (Exception ex) when (!Fx.IsFatal(ex)) + { + this.TryRemove(); + tcs.SetException(ex); + } + + return await tcs.Task; } } @@ -109,10 +126,8 @@ public async Task GetOrCreateAsync(TimeSpan timeout) { throw new ObjectDisposedException(this.GetType().Name); } - else - { - throw new TimeoutException(string.Format(CultureInfo.InvariantCulture, "Timed out trying to create {0}", this.GetType().Name)); - } + + throw new TimeoutException(string.Format(CultureInfo.InvariantCulture, "Creation of {0} did not complete in {1} milliseconds.", typeof(TValue).Name, timeout.TotalMilliseconds)); } protected void Invalidate(TValue instance) @@ -128,6 +143,11 @@ protected void Invalidate(TValue instance) } } + protected virtual bool IsValid(TValue value) + { + return true; + } + protected abstract Task OnCreateAsync(TimeSpan timeout); protected abstract void OnSafeClose(TValue value); @@ -169,24 +189,5 @@ bool TryRemove() } } } - - async Task CreateValue(TaskCompletionSource tcs, TimeSpan timeout) - { - try - { - TValue value = await OnCreateAsync(timeout).ConfigureAwait(false); - tcs.SetResult(value); - - if (this.disposed) - { - OnSafeClose(value); - } - } - catch (Exception ex) when (!Fx.IsFatal(ex)) - { - this.TryRemove(); - tcs.SetException(ex); - } - } } }