// ReSharper disable PossibleInvalidOperationException internal static void SetReplicableNull(Task?task) { try { _replicableLock.Enter(); if (!task.HasValue || (_replicable.HasValue && _replicable.Value.Id == task.Value.Id && _replicable.Value.Item == task.Value.Item)) { _replicable = null; } } finally { _replicableLock.Exit(); } }
public bool DoWork(int expectedId) { try { _executionLock.Enter(); if (expectedId < _runCount) { return(true); } if (_executing == _work.Options.MaximumThreads) { return(false); } _executing++; } finally { _executionLock.Exit(); } // associate the current task with this thread, so that Task.CurrentTask gives the correct result Stack <Task> tasks = null; if (!RunningTasks.TryGet(Thread.CurrentThread, out tasks)) { tasks = new Stack <Task>(); RunningTasks.Add(Thread.CurrentThread, tasks); } tasks.Push(new Task(this)); // execute the task try { _work.DoWork(); } catch (Exception e) { if (_exceptionBuffer == null) { var newExceptions = new List <Exception>(); Interlocked.CompareExchange(ref _exceptionBuffer, newExceptions, null); } lock (_exceptionBuffer) _exceptionBuffer.Add(e); } tasks.Pop(); try { _executionLock.Enter(); _executing--; if (_executing == 0) { if (_exceptionBuffer != null) { _exceptions.Add(_runCount, _exceptionBuffer.ToArray()); } // wait for all children to complete foreach (var child in _children) { child.Wait(); } _runCount++; // open the reset event, so tasks waiting on this once can continue _resetEvent.Set(); // wait for waiting tasks to all exit while (_waitCount > 0) { ; } if (Callback == null) { Requeue(); } else { // if we have a callback, then queue for execution lock (AwaitingCallbacks) AwaitingCallbacks.Add(this); } return(true); } return(false); } finally { _executionLock.Exit(); } }