/// <summary> /// Método que gestiona el evento de fin de ejecución de un proceso en segundo plano /// </summary> /// <param name="sender">Origen del evento</param> /// <param name="e">Resultado de la ejecución del proceso en segundo plano</param> private static void BwRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { var work = sender as BackgroundWorker; if (work != null) { string wHash = work.GetHashCode().ToString(CultureInfo.InvariantCulture); //Comprobamos si el proceso tenía otros subprocesos cacheables pendientes de su ejecución //Y en caso de ser así asignamos a todos el mismo resultado if (IndexDependencies.ContainsKey(wHash)) { string stHash = IndexDependencies[wHash]; lock (CacheDependencies) { IList <long> stickiesDep = CacheDependencies[stHash]; foreach (var stickyId in stickiesDep) { RemoveWork(stickyId); if (!e.Cancelled && e.Error == null) { Hal.Results[stickyId] = e.Result; } } CacheDependencies.Remove(stHash); IndexDependencies.Remove(wHash); } } } }
/// <summary> /// Ejecuta un proceso en segundo plano /// </summary> /// <typeparam name="T">Tipo de parámetro del delegado a invocar</typeparam> /// <param name="sticky">Plan de ejecución</param> private static void RunWork <T>(Sticky <T> sticky) { var work = CreateWork(); string wHash = work.GetHashCode().ToString(CultureInfo.InvariantCulture); Hal.Sonar.Add(sticky.Id, work); //Se comprueba si en el plan de ejecución se tiene en cuenta el cacheo if (sticky.IsCacheable) { lock (CacheDependencies) { if (!CacheDependencies.ContainsKey(sticky.Hash)) { //Creamos el proceso maestro que servirá de referencia para los demás CacheDependencies[sticky.Hash] = new List <long>(); IndexDependencies[wHash] = sticky.Hash; } else { CacheDependencies[sticky.Hash].Add(sticky.Id); return; } } } //Comprobamos si el nuevo proceso es el más prioritario if (Hal.KingHill == null) { Hal.KingHill = new KingHill(wHash, sticky.PriorityPercent); } else { lock (Hal.KingHill) { Hal.KingHill.AddWorker(wHash, sticky.PriorityPercent); } } //Ejecutamos el trabajo work.RunWorkerAsync(sticky); }
/// <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); } }