public static void Run <TState>(ReplicatableUserAction <TState> action, ParallelOptions options, bool stopOnFirstFailure) { // Browser hosts do not support synchronous Wait so we want to run the // replicated task directly instead of going through Task infrastructure if (OperatingSystem.IsBrowser()) { // Since we are running on a single thread, we don't want the action to time out var timeout = int.MaxValue - 1; var state = default(TState) !; action(ref state, timeout, out bool yieldedBeforeCompletion); if (yieldedBeforeCompletion) { throw new Exception("Replicated tasks cannot yield in this single-threaded browser environment"); } } else { int maxConcurrencyLevel = (options.EffectiveMaxConcurrencyLevel > 0) ? options.EffectiveMaxConcurrencyLevel : int.MaxValue; TaskReplicator replicator = new TaskReplicator(options, stopOnFirstFailure); new Replica <TState>(replicator, maxConcurrencyLevel, CooperativeMultitaskingTaskTimeout_RootTask, action).Start(); Replica?nextReplica; while (replicator._pendingReplicas.TryDequeue(out nextReplica)) { nextReplica.Wait(); } if (replicator._exceptions != null) { throw new AggregateException(replicator._exceptions); } } }
protected volatile Task _pendingTask; // the most recently queued Task for this replica, or null if we're done. protected Replica(TaskReplicator replicator, int maxConcurrency, int timeout) { _replicator = replicator; _timeout = timeout; _remainingConcurrency = maxConcurrency - 1; _pendingTask = new Task(s => ((Replica)s).Execute(), this); _replicator._pendingReplicas.Enqueue(this); }
protected Replica(TaskReplicator replicator, int maxConcurrency, int timeout) { Replicator = replicator; Timeout = timeout; RemainingConcurrency = maxConcurrency - 1; PendingTask = new Task(Execute); Replicator._pendingReplicas.Enqueue(this); }
public static void Run <TState>(ReplicableUserAction <TState> action, ParallelOptions options, bool stopOnFirstFailure) { var maxConcurrencyLevel = options.EffectiveMaxConcurrencyLevel > 0 ? options.EffectiveMaxConcurrencyLevel : int.MaxValue; var replicator = new TaskReplicator(options, stopOnFirstFailure); new Replica <TState>(replicator, maxConcurrencyLevel, _cooperativeMultitaskingTaskTimeoutRootTask, action).Start(); while (replicator._pendingReplicas.TryDequeue(out var nextReplica)) { nextReplica.Wait(); } if (replicator._exceptions != null) { throw new AggregateException(replicator._exceptions); } }