public bool DoWork(int expectedID) { using (executionLock.AcquireExclusiveUsing()) { if (expectedID < runCount) { return(true); } if (work == null) { return(false); } if (executing == work.Options.MaximumThreads) { return(false); } executing++; } // 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 { // Set work data to running if able if (WorkData != null) { WorkData.WorkState = ParallelTasks.WorkData.WorkStateEnum.RUNNING; } work.DoWork(WorkData); // Set work data to succeeded if able and not failed if (WorkData != null && WorkData.WorkState == ParallelTasks.WorkData.WorkStateEnum.RUNNING) { WorkData.WorkState = ParallelTasks.WorkData.WorkStateEnum.SUCCEEDED; } } catch (Exception e) { if (exceptionBuffer == null) { var newExceptions = new List <Exception>(); Interlocked.CompareExchange(ref exceptionBuffer, newExceptions, null); } lock (exceptionBuffer) exceptionBuffer.Add(e); } if (tasks != null) { tasks.Pop(); } using (executionLock.AcquireExclusiveUsing()) { executing--; if (executing == 0) { if (exceptionBuffer != null) { #if UNSHARPER //workaround for volatile int to const int& casting problem in c++. int val = runCount; exceptions.Add(val, exceptionBuffer.ToArray()); #else exceptions.Add(runCount, exceptionBuffer.ToArray()); #endif } // wait for all children to complete foreach (var child in children) { child.Wait(); } runCount++; // open the reset event, so tasks waiting on this one can continue resetEvent.Set(); // wait for waiting tasks to all exit while (waitCount > 0) { ; } if (Callback == null && DataCallback == null) { Requeue(); } else { // if we have a callback, then queue for execution CompletionCallbacks.Add(this); } return(true); } return(false); } }
public bool DoWork(int expectedID) { using (executionLock.AcquireExclusiveUsing()) { if (expectedID < runCount) { return(true); } if (work == null) { return(false); } if (executing == work.Options.MaximumThreads) { return(false); } executing++; } // 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); } if (tasks != null) { tasks.Pop(); } using (executionLock.AcquireExclusiveUsing()) { 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 one 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 CompletionCallbacks.Enqueue(this); } return(true); } return(false); } }