public DataSourceController( IDataSourceOrchestrator orchestrator, TasksToRun tasksToRun) { _orchestrator = orchestrator; _tasksToRun = tasksToRun; }
/// <summary> /// The implementation of this interface method enqueus the action to be run on the custom /// task scheduler. The task scheduler runs asynchronously, however it has only one slot, that allows to maintain /// the order of execution for each of the items. /// </summary> public void SaveEntityStateAsyncAndDispose() { lock (Locker) { this.DetectChanges(); if (!TasksToRun.Any()) { var task = GetSaveTask(); TasksToRun.Enqueue(task); task.Start(); } else { TasksToRun.Enqueue(GetSaveTask()); } } }
protected override void QueueTask(Task task) { // If we've been disposed, no one should be queueing if (DisposeCancellation.IsCancellationRequested) { throw new ObjectDisposedException(GetType().Name); } // add the task to the blocking queue TasksToRun.Add(task); if (Interlocked.CompareExchange(ref _countThreads, 0, 0) >= MaximumConcurrencyLevel) { return; } Interlocked.Increment(ref _countThreads); Task.Factory.StartNew(ThreadBasedDispatchLoop, TaskCreationOptions.DenyChildAttach); }
/// <summary>The dispatch loop run by all threads in this scheduler.</summary> private void ThreadBasedDispatchLoop() { TaskProcessingThread = true; try { // If a thread abort occurs, we'll try to reset it and continue running. while (true) { try { // For each task queued to the scheduler, try to execute it. foreach (var task in TasksToRun.GetConsumingEnumerable(DisposeCancellation.Token)) { Interlocked.Increment(ref _countExecutableTasks); TryExecuteTask(task); Interlocked.Decrement(ref _countExecutableTasks); } } catch (ThreadAbortException) { // If we received a thread abort, and that thread abort was due to shutting down // or unloading, let it pass through. Otherwise, reset the abort so we can // continue processing work items. if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload()) { Thread.ResetAbort(); } } } } catch (OperationCanceledException) { // If the scheduler is disposed, the cancellation token will be set and // we'll receive an OperationCanceledException. That OCE should not crash the process. } finally { TaskProcessingThread = false; } }
public JobController(TasksToRun tasks) => _tasks = tasks;
public BackgroundService(TasksToRun tasks) => _tasks = tasks;