/// <summary> /// Método que controla el fin de la ejecución de un proceso en segundo plano /// </summary> /// <param name="stickyId">Identificador del plan de ejecución</param> /// <param name="e">Argumentos del evento de fin de ejecución</param> /// <param name="work">Proceso en segundo plano</param> private static void EndWorkExecution(long stickyId, DoWorkEventArgs e, BackgroundWorker work = null) { Hal.Results[stickyId] = e.Result; //Comprobamos si el trabajo es periodico if (!StickyUtils.GetStickyProp <bool>(e.Argument, "IsPeriodic")) { //Finalizamos la ejecución del trabajo RemoveWork(stickyId); if (work != null) { lock (Hal.KingHill) { Hal.KingHill.ReleasePriority(work.GetHashCode().ToString(CultureInfo.InvariantCulture)); } } } else { //Pausamos el trabajo y lo volvemos a ejecutar de nuevo Thread.Sleep(StickyUtils.GetStickyProp <int>(e.Argument, "MillisecondsDelay")); var newWork = CreateWork(); newWork.RunWorkerAsync(e.Argument); } }
/// <summary> /// Método que gestiona el evento de ejecución de un proceso en segundo plano /// </summary> /// <param name="sender">Proceso en segundo plano</param> /// <param name="e">Argumentos del evento</param> private static void BwDoWork(object sender, DoWorkEventArgs e) { //Obtenemos los datos del trabajo long id = StickyUtils.GetStickyId(e.Argument); var worker = sender as BackgroundWorker; //Comprobamos si hay una cancelación pendiente del trabajo if (worker != null && worker.CancellationPending) { e.Cancel = true; RemoveWork(id); return; } var isCacheable = StickyUtils.GetStickyProp <bool>(e.Argument, "IsCacheable"); //Comprobamos si se quiere utilizar la cache if (isCacheable) { var hash = StickyUtils.GetStickyProp <string>(e.Argument, "Hash"); //Comprobamos si el resultado ya se encuentra en cache if (SonarCache.ContainsKey(hash)) { e.Result = SonarCache[hash]; } else { //En caso contrario calculamos y guardamos en cache e.Result = StickyUtils.ExecuteSticky(e.Argument, worker); SonarCache[hash] = e.Result; } } else { //Ejecución normal de trabajos sin cache e.Result = StickyUtils.ExecuteSticky(e.Argument, worker); } EndWorkExecution(id, e, worker); }
/// <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); } }