private CalculationProcessInfo CreateCalculationProcessInfo(TParameters parameters) { CalculationProcessInfo calculationProcessInfo = new CalculationProcessInfo(); processingCalculations.Add(parameters, calculationProcessInfo); return(calculationProcessInfo); }
private bool TryAcquireCalculationWait( TParameters parameters, out CalculationProcessInfo calculationProcessInfo) { bool result; try { } // Finally block will not be interrupted by thread aborting finally { result = processingCalculations.TryGetValue(parameters, out calculationProcessInfo); if (result) { checked { calculationProcessInfo.WaitCount++; } } } return(result); }
private void ReleaseCalculationWait( TParameters parameters, CalculationProcessInfo calculationProcessInfo) { calculationProcessInfo.WaitCount--; if (calculationProcessInfo.Done && (calculationProcessInfo.WaitCount == 0)) { processingCalculations.Remove(parameters); calculationProcessInfo.Dispose(); } }
private void CompleteCalculationProcessInfo( TParameters parameters, CalculationProcessInfo calculationProcessInfo) { calculationProcessInfo.Done = true; if (calculationProcessInfo.WaitCount > 0) { calculationProcessInfo.Event.Set(); } else { processingCalculations.Remove(parameters); calculationProcessInfo.Dispose(); } }
/// <summary> /// Returns cached result, or calculates a new one, or waits until the calculation is complete. /// Thread-safe. /// </summary> /// <param name="parameters">Calculation parameters</param> /// <returns>Calculation result</returns> public TResult GetResult(TParameters parameters) { if (parameters == null) { throw new ArgumentNullException("parameters"); } TResult result; while (true) { CalculationProcessInfo calculationProcessInfo = null; bool shouldWait = false; try { lock (syncRoot) { if (cachedResults.TryGetValue(parameters, out result)) { return(result); } shouldWait = TryAcquireCalculationWait(parameters, out calculationProcessInfo); if (!shouldWait) { calculationProcessInfo = CreateCalculationProcessInfo(parameters); } } if (shouldWait) { calculationProcessInfo.Event.WaitOne(); } else { result = calculation(parameters); lock (syncRoot) cachedResults.Add(parameters, result); return(result); } } finally { lock (syncRoot) { if (shouldWait) { ReleaseCalculationWait(parameters, calculationProcessInfo); } else if (calculationProcessInfo != null) { CompleteCalculationProcessInfo(parameters, calculationProcessInfo); } } } } }