private Action CreateTaskBody(TaskExecutionInfo executionInfoLocal, TaskTypeInfo taskTypeInfo) { return(() => { try { executionInfoLocal.SendAliveSignal(); executionInfoLocal.SetTaskThread(Thread.CurrentThread); if (executionInfoLocal.CancellationTokenSource.IsCancellationRequested) { return; } if (!SetRunningStatus(executionInfoLocal, taskTypeInfo)) { return; } executionInfoLocal.SendAliveSignal(); //Flags executionInfoLocal right before invoking the task implementation executionInfoLocal.RealTaskInvokedFlag = true; taskTypeInfo.Invoke(executionInfoLocal.TaskDefinition.JsonParameters, executionInfoLocal); SetCompletedOrCancelledStatus(executionInfoLocal); } catch (ThreadAbortException ex) { //Tries to save information about the task status. //Reverts ThreadAbort Thread.ResetAbort(); SetAbortedStatus(executionInfoLocal); } catch (Exception ex) { ex.LogException(); SetCompletedOrCancelledStatus(executionInfoLocal); } finally { try { //See comment below executionInfoLocal.LockWillBeReleasedFlag = true; _taskManager.LockManager.Release(executionInfoLocal.LockInfo); //**** LockWillBeReleasedFlag avoids having the task being aborted right here when it's about to end, because we just released the lock // and the lifetime manager could try to cancel it forcefully. } catch (Exception ex) { ex.LogException(); } } }); }
internal void Invoke(string jsonParameter, TaskExecutionInfo executionInfo) { object parameter = null; if (jsonParameter != null) { parameter = JsonConvert.DeserializeObject(jsonParameter, this.ParamType); } var instance = Activator.CreateInstance(this.TaskType); TaskTypeInfo.TypedInvoke((dynamic)instance, (dynamic)parameter, executionInfo); }
private TaskTypeInfo CreateTaskInfo(Type type, TaskSettings settings) { Type paramType = null; var genericType = GetGenericTaskType(type, out paramType); if (genericType == null) { throw new ApplicationException(String.Format("The type [{0}] is not a valid Task or Task<P> type.", type.FullName)); } TaskTypeInfo info = TaskTypeInfo.CreateFromType(type, paramType, settings); return(info); }
private bool SetRunningStatus(TaskExecutionInfo executionInfoLocal, TaskTypeInfo taskTypeInfo) { var lockInfo = executionInfoLocal.LockInfo; var taskDefinition = executionInfoLocal.TaskDefinition; //It may be that the task scheduler took too long to start the thread. //Renews the lock. Ignores the task if it doesn't acquire lock if (!_taskManager.LockManager.TryRenewLock(lockInfo, taskTypeInfo.LockCycle, retryLock: true)) { return(false); } using (var tr = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled)) using (var conn = _taskManager.CreateConnection()) using (var command = DbAccessHelper.CreateDbCommand(conn, SET_RUNNING_STATUS_SQL)) { //milisecond precision var lastRunAt = _taskManager.GetUtcNow().SetFractionalSecondPrecision(3); var lockState = lockInfo.AsImmutable(); command.Parameters.Add(new SqlParameter("Id", taskDefinition.Id)); command.Parameters.Add(new SqlParameter("LastRunAt", System.Data.SqlDbType.DateTime2) { Value = lastRunAt }); command.Parameters.Add(new SqlParameter("LockedUntil", System.Data.SqlDbType.DateTime2) { Value = lockState.LockedUntil }); //Has the task been deleted or already handled? if (command.ExecuteNonQuery() != 1) { return(false); } executionInfoLocal.LastRunAt = lastRunAt; return(true); } }