예제 #1
0
        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);
        }
예제 #2
0
        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());
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
 public virtual void OnRemove()
 {
     OnActionFailed?.Invoke();
     state = States.Disabled;
 }
예제 #5
0
 protected void ActionFailure() => OnActionFailed?.Invoke();