internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued, object threadStatics) { TaskScheduler executingTaskScheduler = task.ExecutingTaskScheduler; if ((executingTaskScheduler != this) && (executingTaskScheduler != null)) { return(executingTaskScheduler.TryRunInline(task, taskWasPreviouslyQueued)); } if (((executingTaskScheduler == null) || (task.m_action == null)) || ((task.IsDelegateInvoked || task.IsCanceled) || !Task.CurrentStackGuard.TryBeginInliningScope())) { return(false); } bool flag = false; try { flag = this.TryExecuteTaskInline(task, taskWasPreviouslyQueued); } finally { Task.CurrentStackGuard.EndInliningScope(); } if ((flag && !task.IsDelegateInvoked) && !task.IsCanceled) { throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_InconsistentStateAfterTryExecuteTaskInline")); } return(flag); }
/// <summary> /// Attempts to execute the target task synchronously. /// </summary> /// <param name="task">The task to run.</param> /// <param name="taskWasPreviouslyQueued">True if the task may have been previously queued, /// false if the task was absolutely not previously queued.</param> /// <param name="threadStatics">The state retrieved from GetThreadStatics</param> /// <returns>True if it ran, false otherwise.</returns> // [SecuritySafeCritical] internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued, object threadStatics) { // Do not inline unstarted tasks (i.e., task.ExecutingTaskScheduler == null). // Do not inline TaskCompletionSource-style (a.k.a. "promise") tasks. // No need to attempt inlining if the task body was already run (i.e. either TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bits set) TaskScheduler ets = task.ExecutingTaskScheduler; // Delegate cross-scheduler inlining requests to target scheduler if (ets != this && ets != null) { return(ets.TryRunInline(task, taskWasPreviouslyQueued)); } if ((ets == null) || (task.m_action == null) || task.IsDelegateInvoked || task.IsCanceled) { return(false); } // Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that // 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us // 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP) bool bInlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued); // If the custom scheduler returned true, we should either have the TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bit set // Otherwise the scheduler is buggy if (bInlined && !(task.IsDelegateInvoked || task.IsCanceled)) { throw new InvalidOperationException(Strings.TaskScheduler_InconsistentStateAfterTryExecuteTaskInline); } return(bInlined); }
internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued) { TaskScheduler executingTaskScheduler = task.ExecutingTaskScheduler; if (executingTaskScheduler != this && executingTaskScheduler != null) { return(executingTaskScheduler.TryRunInline(task, taskWasPreviouslyQueued)); } StackGuard currentStackGuard; if (executingTaskScheduler == null || task.m_action == null || task.IsDelegateInvoked || task.IsCanceled || !(currentStackGuard = Task.CurrentStackGuard).TryBeginInliningScope()) { return(false); } bool flag = false; try { task.FireTaskScheduledIfNeeded(this); flag = this.TryExecuteTaskInline(task, taskWasPreviouslyQueued); } finally { currentStackGuard.EndInliningScope(); } if (flag && !task.IsDelegateInvoked && !task.IsCanceled) { throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_InconsistentStateAfterTryExecuteTaskInline")); } return(flag); }