/// <summary> /// Выполнить действие в отдельном потоке и транзакции /// --- /// объекты должны быть независимы в действии, можно передавать Id сущности и после выполнения в исходном потоке вызвать Refresh /// </summary> /// <param name="action"> действие </param> /// <param name="name">название операции</param> /// <param name="errorCallback">обработка ошибки</param> /// <param name="successCallback">действие после успеха</param> /// <param name="minutes">количество минут выделенное на операцию (максимум 9)</param> public static void InNewThread( this Action action, string name, Action <Exception> errorCallback, Action successCallback, int minutes = 2) { Exception exception = null; Thread thread = null; try { thread = ThreadStarter.StartNewThread((ThreadStart) delegate { var backgroundTask = new BackgroundTask(() => { var securityService = Locator.GetService <ISecurityService>(); securityService.RunByUser(UserManager.Instance.Load(SecurityConstants.AdminUserUid), () => { var unitOfWorkManager = Locator.GetServiceNotNull <IUnitOfWorkManager>(); using (var unitOfWork = unitOfWorkManager.Create(string.Empty, true, System.Data.IsolationLevel.ReadCommitted)) { try { action.Invoke(); unitOfWork.Commit(); } catch (Exception ex) { unitOfWork.Rollback(); exception = ex; } } }); }, typeof(Action), action.Method.Name, name); backgroundTask.Execute(); }); thread.IsBackground = true; if (!thread.Join(TimeSpan.FromMinutes(minutes))) { thread.Abort(); var message = $"Действие \"{name}\" выполнялось более {minutes} минут и было прервано"; exception = exception != null ? new Exception(message, exception) : new Exception(message); } if (exception != null) { if (errorCallback != null) { errorCallback.Invoke(exception); } else { throw exception; } } else { successCallback?.Invoke(); } } catch (ThreadAbortException) { thread?.Abort(); throw; } }
/// <summary> /// Heartbeat thread, waits for signal that something has been queued for processing. /// </summary> protected virtual void Heartbeat() { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); do { if (shutdown) { return; } Trace.WriteLine("Processor idle, waiting for signal..."); // Wait for the signal to be set signal.WaitOne(); Trace.WriteLine("Got signal, processing task"); // Exit heartbeat if (shutdown) { return; } try { queuedBackgroundTask.OnStarted(); queuedBackgroundTask.Execute(); queuedBackgroundTask.OnSuccess(); } //catch (ThreadAbortException) //{ // Thread.ResetAbort(); //} catch (Exception ex) { try { Logger.Error("An error has occured while executing the task {0}, Exception = {1}", LogSource.TaskQueue, this, ex); queuedBackgroundTask.OnFailure(); } catch (Exception ex1) { Logger.Error("A fatal background task exception has occured. Exception = {0}", LogSource.TaskQueue, ex1); } } finally { try { queuedBackgroundTask.OnCompleted(); ToggleStatus(true); queuedBackgroundTask = null; OnPropertyChanged("QueuedBackgroundTask"); } catch (Exception ex) { Logger.Error("A fatal background task exception has occured. Exception = {0}", LogSource.TaskQueue, ex); } } }while (true); }