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(); } } }); }
private void SetCompletedOrCancelledStatus(TaskExecutionInfo executionInfoLocal) { executionInfoLocal.SendAliveSignal(); var lockInfo = executionInfoLocal.LockInfo; var taskDefinition = executionInfoLocal.TaskDefinition; /* We should not renew lock here because the task has already completed */ //If the task didn't run, don't do anything. if (executionInfoLocal.LastRunAt == null) { return; } try { using (var tr = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled)) using (var conn = _taskManager.CreateConnection()) using (var command = DbAccessHelper.CreateDbCommand(conn, SET_COMPLETED_STATUS_FOR_RUNNING)) { var newStatus = executionInfoLocal.IsCancellationRequested ? Distributed.SingleTaskStatus.CompletedCancelled : Distributed.SingleTaskStatus.Completed; command.Parameters.Add(new SqlParameter("Id", taskDefinition.Id)); command.Parameters.Add(new SqlParameter("LastRunAt", System.Data.SqlDbType.DateTime2) { Value = executionInfoLocal.LastRunAt }); command.Parameters.Add(new SqlParameter("NewStatus", (int)newStatus)); command.ExecuteNonQuery(); } } catch (Exception ex) { ex.LogException(); } }