[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")] // TODO: fix public TValue GetOrCreateValue(TKey key, Func <TValue> create) { bool lockTaken = false; try { MonitorUtils.Enter(data, ref lockTaken); PublishInfo <TValue> pubValue; if (data.TryGetValue(key, out pubValue)) { if (pubValue.Value == null && pubValue.Exception == null) { pubValue.PrepareForWait(); MonitorUtils.Exit(data, ref lockTaken); try { pubValue.WaitForPublish(); } finally { MonitorUtils.Enter(data, ref lockTaken); pubValue.FinishWait(); } } if (pubValue.Exception != null) { throw new Exception("Error", pubValue.Exception); } return(pubValue.Value); } TValue ret; // publish the empty PublishInfo data[key] = pubValue = new PublishInfo <TValue>(); // release our lock while we create the new value // then re-acquire the lock and publish the info. MonitorUtils.Exit(data, ref lockTaken); try { try { ret = create(); Debug.Assert(ret != null, "Can't publish a null value"); } finally { MonitorUtils.Enter(data, ref lockTaken); } } catch (Exception e) { pubValue.PublishError(e); throw; } pubValue.PublishValue(ret); return(ret); } finally { if (lockTaken) { Monitor.Exit(data); } } }