/// <summary>s /// Ejecuta un proceso en segundo plano o lo coloca en la cola de ejecución /// en caso de no quedar ningún hilo libre /// </summary> /// <typeparam name="T">Tipo de parámetro del delegado a invocar</typeparam> /// <param name="sticky">Plan de ejecución</param> /// <param name="forceExecution">Indica que se ejecuta sin tener en cuenta el número de procesos en ejecución</param> /// <param name="exeCxt">Contexto de ejecución </param> /// <returns>Identificador del plan de ejecución</returns> public static long AddWork <T>(Sticky <T> sticky, bool forceExecution, ExecutionContext <T> exeCxt) { //Iniciamos el sonar si no estaba activo if (Hal.Sonar == null) { Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; Hal.Sonar = new Dictionary <long, BackgroundWorker>(Hal.MaxParallelsProcess + 5); Hal.Results = new Dictionary <long, object>(Hal.MaxParallelsProcess + 5); SonarProgress = new Dictionary <long, int>(); SonarCache = new Dictionary <string, object>(); ProcessInQueue = new Queue <object>(); ProcessInQueueIndex = new List <long>(); CacheDependencies = new Dictionary <string, IList <long> >(); IndexDependencies = new Dictionary <string, string>(); } if (exeCxt != null) { exeCxt.AttachWork(sticky, forceExecution); return(-1); } //Asignamos un ticket de ejecución al trabajo sticky.Id = Hal.GetTicket(); //Creamos el trabajo y lo ejecutamos si no excede //el limite de hilos en ejecución o es prioritario if (Hal.Sonar.Count < Hal.MaxParallelsProcess || forceExecution) { RunWork(sticky); } else { //Si hay demasiados trabajos en paralelo //se encola para su futura ejecución ProcessInQueue.Enqueue(sticky); ProcessInQueueIndex.Add(sticky.Id); } return(sticky.Id); }
/// <summary> /// Elimina un proceso en segundo plano por su identificador /// </summary> /// <param name="stickyId">Identificador del plan de ejecución</param> public static void RemoveWork(long stickyId) { //Comprobamos si aún existe en el contexto de ejecución if (!Hal.Sonar.ContainsKey(stickyId)) { return; } //Obtenemos el trabajo y lo borramos var work = Hal.Sonar[stickyId]; work.CancelAsync(); Hal.Sonar.Remove(stickyId); //Obtenemos el próximo trabajo en cola y lo ejecutamos object sticky = null; //Bloqueamos el acceso a la cola para impedir que los //diferentes hilos inicien el mismo trabajo lock (ProcessInQueue) { if (ProcessInQueue.Count > 0) { sticky = ProcessInQueue.Dequeue(); } } //Si existe algún trabajo en cola lo ejecutamos en el sonar if (sticky != null) { long id = StickyUtils.GetStickyId(sticky); var hash = StickyUtils.GetStickyProp <string>(sticky, "Hash"); work = CreateWork(); string wHash = work.GetHashCode().ToString(CultureInfo.InvariantCulture); Hal.Sonar.Add(id, work); if (StickyUtils.GetStickyProp <bool>(sticky, "IsCacheable")) { lock (CacheDependencies) { if (!CacheDependencies.ContainsKey(hash)) { CacheDependencies[hash] = new List <long>(); IndexDependencies[wHash] = hash; } else { CacheDependencies[hash].Add(id); return; } } } var priorPer = StickyUtils.GetStickyProp <int>(sticky, "PriorityPercent"); if (Hal.KingHill == null) { Hal.KingHill = new KingHill(wHash, priorPer); } else { lock (Hal.KingHill) { Hal.KingHill.AddWorker(wHash, priorPer); } } //Ejecutamos el trabajo work.RunWorkerAsync(sticky); } }