private JobTaskResult RunAction(IEnumerable <Task <JobTaskResult> > parentTasks) { if (parentTasks.Any(x => x.Result.ActionCanceled)) { State = JobState.ActionSkipped; OnActionFailed?.Invoke(this, new JobFailedArgs { Exception = new Exception("Skipped because one of parent tasks failed") }); return(JobTaskResult.Failed()); } var result = new JobTaskResult(); var withSemaphore = jobsContext.UseActionSemaphore; if (withSemaphore) { State = JobState.ActionWaitForSemaphore; jobsContext.ActionSemaphore.Wait(); } try { OnActionExecuting?.Invoke(this, new JobArgs()); State = JobState.ActionExecuting; Action(new JobActionFeed(result)); if (result.ActionCanceled) { state = JobState.ActionCanceled; } else { OnActionExecuted?.Invoke(this, new JobArgs()); state = JobState.ActionExecuted; } } catch (Exception ex) { var args = new JobFailedArgs { Exception = ex }; result.ActionCanceled = true; OnActionFailed?.Invoke(this, args); State = JobState.ActionFailed; } if (withSemaphore) { jobsContext.ActionSemaphore.Release(); } return(result); }
private JobTaskResult RunBackAction(IEnumerable <Task <JobTaskResult> > childTasks) { if (childTasks.Any(x => x.IsFaulted)) { OnActionFailed?.Invoke(this, new JobFailedArgs { Exception = new Exception("Skipped because one of the tasks failed") }); ////State = JobState.BackActionSkipped <- back action cannot be skipped when chld action fails } var withSemaphore = jobsContext.UseBackActionSemaphore; if (withSemaphore) { State = JobState.BackActionWaitForSemaphore; jobsContext.BackActionSemaphore.Wait(); } try { OnBackActionExecuting?.Invoke(this, new JobArgs()); State = JobState.BackActionExecuting; BackAction(); OnBackActionExecuted?.Invoke(this, new JobArgs()); State = JobState.BackActionExecuted; } catch (Exception ex) { OnBackActionFailed?.Invoke(this, new JobFailedArgs { Exception = ex }); State = JobState.BackActionFailed; } if (withSemaphore) { jobsContext.BackActionSemaphore.Release(); } return(new JobTaskResult()); }
public void Queue(T target, string uniqueKey, Action <T> action) { if (disposedValue) { throw new ObjectDisposedException(nameof(AsyncActionQueue <T>)); } if (thread == null || !thread.IsAlive) { Thread localThread = null; thread = localThread = new Thread(() => { while (true) { lock (queue) { while (!enabled || queue.Count == 0) { if (thread != localThread) { Trace.WriteLine($"Stopping {localThread.Name} thread"); return; } Monitor.Wait(queue); } var startedTasks = new List <ActionContainer>(); lock (running) foreach (var task in queue) { if (running.Contains(task.UniqueKey)) { continue; } running.Add(task.UniqueKey); startedTasks.Add(task); var taskToRun = task; ThreadPool.QueueUserWorkItem((state) => { try { taskToRun.Action.Invoke(taskToRun.Target); } catch (Exception e) { var toUpdateTarget = taskToRun.Target; Program.Schedule(() => { if (OnActionFailed != null) { OnActionFailed.Invoke(toUpdateTarget, e); } else { Trace.WriteLine($"Action failed for '{taskToRun.Target}': {e}"); } }); } lock (running) running.Remove(taskToRun.UniqueKey); lock (queue) if (queue.Count > 0) { Monitor.Pulse(queue); } }); } foreach (var startedTask in startedTasks) { queue.Remove(startedTask); } } } }) { Name = threadName, IsBackground = true, }; Trace.WriteLine($"Starting {localThread.Name} thread"); thread.Start(); } lock (queue) { if (!allowDuplicates) { foreach (var queued in queue) { if (queued.Target.Equals(target)) { return; } } } queue.Add(new ActionContainer() { Target = target, UniqueKey = uniqueKey, Action = action }); Monitor.Pulse(queue); } }
public virtual void OnRemove() { OnActionFailed?.Invoke(); state = States.Disabled; }
protected void ActionFailure() => OnActionFailed?.Invoke();