// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Diagnostics { /// /// This task scheduler will block queuing new tasks if upper bound has met. /// internal class DiagnosticEventTaskScheduler : TaskScheduler { private readonly Thread _thread; private readonly BlockingCollection _tasks; public DiagnosticEventTaskScheduler(int blockingUpperBound) { _tasks = new BlockingCollection(blockingUpperBound); _thread = new Thread(Start) { Name = "Roslyn Diagnostics", IsBackground = true }; _thread.Start(); } private void Start() { while (true) { var task = _tasks.Take(); bool ret = this.TryExecuteTask(task); } } protected override void QueueTask(Task task) { _tasks.Add(task); } protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) { // NOTE: TPL will ensure only one task ever run when running scheduled task. and since this is only used // in diagnostic events, we know task will always run sequencely. so no worry about reverted order here. return this.TryExecuteTask(task); } protected override IEnumerable GetScheduledTasks() { // debugger will use this method to get scheduled tasks for this scheduler return _tasks.ToArray(); } } }