// [1] Use TaskCreationOptions.LongRunning here not because the consituent operations are // coarse-grained (they aren't and could in fact benefit from parallelization in future iterations), // but because this hint informs the scheduler not to schedule the task on the local queue // which - given that this method is called from an HTTP-request-handling thread - would // schedule it on the same work queue that future HTTP requests would be serviced from. // Further information here: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler?view=netframework-4.8#long-running-tasks public object Queue(PipelineBase pipeline, PipelineRequestTracker?initiator, bool trackAfterCompletion = false) { _pipelinesMutex.WaitOne(); if (_pipelines.ContainsKey(pipeline.Id)) { return(null); } if (pipeline.Status < PipelineBase.PipelineStatus.Pending) { return(null); } var tracker = new PipelineTracker() { Pipeline = pipeline, Initiator = initiator, Created = DateTime.UtcNow, LastAccessed = null, QueueToken = Guid.NewGuid().ToString(), OriginalCompletionHandler = pipeline.CompletionHandler, TrackAfterCompletion = trackAfterCompletion }; pipeline.CompletionHandler = OnPipelineStateChance; tracker.Task = Task.Factory.StartNew(pipeline.Execute, TaskCreationOptions.LongRunning /* [1] */); _pipelines[pipeline.Id] = tracker; _pipelinesMutex.ReleaseMutex(); return(_pipelines[pipeline.Id].QueueToken); }
public bool Cancel(Guid pId, object token, PipelineRequestTracker?cancelor) { var rv = false; var realId = ResolveId(pId); PipelineTracker pipe = null; _pipelinesMutex.WaitOne(); if (_pipelines.ContainsKey(realId) && (pipe = _pipelines[realId]).QueueToken.Equals(token)) { if (rv = pipe.Pipeline.Cancel()) { pipe.Cancelor = cancelor; } } _pipelinesMutex.ReleaseMutex(); return(rv); }