// Enqueue a work item to a given context public void QueueWorkItem(IWorkItem workItem) { #if DEBUG if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace("QueueWorkItem " + workItem); } #endif var workItemGroup = GetWorkItemGroup(workItem.GrainContext); if (applicationTurnsStopped && (workItemGroup != null) && !workItemGroup.IsSystemGroup) { // Drop the task on the floor if it's an application work item and application turns are stopped var msg = string.Format("Dropping work item {0} because application turns are stopped", workItem); logger.Warn(ErrorCode.SchedulerAppTurnsStopped_1, msg); return; } if (workItemGroup?.TaskScheduler is TaskScheduler scheduler) { // This will make sure the TaskScheduler.Current is set correctly on any task that is created implicitly in the execution of this workItem. // We must wrap any work item in Task and enqueue it as a task to the right scheduler via Task.Start. Task t = TaskSchedulerUtils.WrapWorkItemAsTask(workItem); t.Start(scheduler); } else { // Note that we do not use UnsafeQueueUserWorkItem here because we typically want to propagate execution context, // which includes async locals. #if NETCOREAPP ThreadPool.QueueUserWorkItem(ExecuteWorkItemAction, workItem, preferLocal: true); #else ThreadPool.QueueUserWorkItem(ExecuteWorkItemCallback, workItem); #endif } }
// Enqueue a work item to a given context public void QueueWorkItem(IWorkItem workItem, ISchedulingContext context) { #if DEBUG if (logger.IsVerbose2) { logger.Verbose2("QueueWorkItem " + context); } #endif if (workItem is TaskWorkItem) { var error = String.Format("QueueWorkItem was called on OrleansTaskScheduler for TaskWorkItem {0} on Context {1}." + " Should only call OrleansTaskScheduler.QueueWorkItem on WorkItems that are NOT TaskWorkItem. Tasks should be queued to the scheduler via QueueTask call.", workItem.ToString(), context); logger.Error(ErrorCode.SchedulerQueueWorkItemWrongCall, error); throw new InvalidOperationException(error); } var workItemGroup = GetWorkItemGroup(context); if (applicationTurnsStopped && (workItemGroup != null) && !workItemGroup.IsSystemGroup) { // Drop the task on the floor if it's an application work item and application turns are stopped var msg = string.Format("Dropping work item {0} because application turns are stopped", workItem); logger.Warn(ErrorCode.SchedulerAppTurnsStopped_1, msg); return; } workItem.SchedulingContext = context; // We must wrap any work item in Task and enqueue it as a task to the right scheduler via Task.Start. // This will make sure the TaskScheduler.Current is set correctly on any task that is created implicitly in the execution of this workItem. if (workItemGroup == null) { Task t = TaskSchedulerUtils.WrapWorkItemAsTask(workItem, context, this); t.Start(this); } else { var runner = context.IsReactiveComputation ? workItemGroup.RcTaskRunner : workItemGroup.TaskRunner; // Create Task wrapper for this work item Task t = TaskSchedulerUtils.WrapWorkItemAsTask(workItem, context, runner); t.Start(runner); } }