/// <summary> /// Blocks the thread while waiting for a result. /// </summary> /// <param name="tcs"> /// The <see cref="TaskCompletionSource{TResult}"/> in use for signalling result is available. /// </param> /// <param name="timeout"> /// (optional)<br/> /// Specifies a timeout. If operation times our a default result will be sent back. /// </param> /// <param name="cts"> /// (optional)<br/> /// A cancellation token source, allowing operation cancellation (from a different thread). /// </param> /// <typeparam name="T"> /// The type of result being requested. /// </typeparam> /// <returns> /// An <see cref="Outcome{T}"/> value, signalling success/failure while also carrying the requested /// result on success; otherwise an <see cref="Exception"/>. /// </returns> public static Outcome <T> AwaitResult <T>( this TaskCompletionSource <T> tcs, TimeSpan?timeout = null, CancellationTokenSource cts = null) { if (tcs.Task.Status >= TaskStatus.RanToCompletion) { return(Outcome <T> .Success(tcs.Task.Result)); } var awaiter = tcs.Task.ConfigureAwait(false).GetAwaiter(); var useTimeout = timeout.HasValue ? DateTime.Now.Add(timeout.Value) : DateTime.MaxValue; var isTimedOut = false; var isCancelled = false; while (!awaiter.IsCompleted && !isTimedOut && !isCancelled) { Task.Delay(10); isTimedOut = DateTime.Now >= useTimeout; isCancelled = cts?.IsCancellationRequested ?? false; } return(tcs.Task.Status >= TaskStatus.RanToCompletion ? Outcome <T> .Success(tcs.Task.Result) : Outcome <T> .Fail( isTimedOut ?new Exception("Result could not be created before operation timed out") : new Exception("Result could not be created. Operation was cancelled"))); }
/// <summary> /// Looks for and returns a value identified by one or more keys. /// </summary> /// <param name="keys"> /// One or more keys to look for. /// </param> /// <returns></returns> public Outcome <string> Get(params string[] keys) { if (!keys.Any()) { return(Outcome <string> .Fail( new ArgumentOutOfRangeException(nameof(keys), $"No value found for key(s): {keys.ConcatCollection(" ")}"))); } var index = -1; var i = -1; var comparison = _ignoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture; foreach (var s in _args) { ++i; if (!keys.Any(i => i.Equals(s, comparison))) { continue; } index = i; break; } return(index == -1 ? Outcome <string> .Fail(new ArgumentOutOfRangeException(nameof(keys), $"Value not found: {keys.ConcatCollection(" | ")}")) : getValueForIndex(index)); }
Outcome <string[]> tryParse(string value, StringComparison comparison = StringComparison.Ordinal) { if (string.IsNullOrEmpty(value)) { return(Outcome <string[]> .Fail(new FormatException($"Invalid {typeof(MultiStringValue)} format: \"{value}\""))); } var split = value.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries); if (split.Length == 0) { return(Outcome <string[]> .Fail(new FormatException($"Invalid {typeof(MultiStringValue)} format: \"{value}\""))); } var roles = new List <string>(); foreach (var s in split) { var trimmed = s.Trim(); var isValidItem = OnValidateItem(trimmed, comparison); if (!isValidItem) { return(Outcome <string[]> .Fail(isValidItem.Exception)); } roles.Add(trimmed); } return(Outcome <string[]> .Success(roles.ToArray())); }