// 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
            }
        }
Exemple #2
0
        // 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);
            }
        }