I’m having a hard time finding a task scheduler on which I can schedule prioritised tasks but can also handle “wrapped” tasks. It is something like what Task.Run tries to solve, but you cannot specify a task scheduler to Task.Run.
I have been using a QueuedTaskScheduler from the Parallel Extensions Extras Samples to solve the task priority requirement (also suggested by this post).
Here is my example:
class Program
{
private static QueuedTaskScheduler queueScheduler = new QueuedTaskScheduler(targetScheduler: TaskScheduler.Default, maxConcurrencyLevel: 1);
private static TaskScheduler ts_priority1;
private static TaskScheduler ts_priority2;
static void Main(string[] args)
{
ts_priority1 = queueScheduler.ActivateNewQueue(1);
ts_priority2 = queueScheduler.ActivateNewQueue(2);
QueueValue(1, ts_priority2);
QueueValue(2, ts_priority2);
QueueValue(3, ts_priority2);
QueueValue(4, ts_priority1);
QueueValue(5, ts_priority1);
QueueValue(6, ts_priority1);
Console.ReadLine();
}
private static Task QueueTask(Func<Task> f, TaskScheduler ts)
{
return Task.Factory.StartNew(f, CancellationToken.None, TaskCreationOptions.HideScheduler | TaskCreationOptions.DenyChildAttach, ts);
}
private static Task QueueValue(int i, TaskScheduler ts)
{
return QueueTask(async () =>
{
Console.WriteLine("Start {0}", i);
await Task.Delay(1000);
Console.WriteLine("End {0}", i);
}, ts);
}
}
The typical output of the example above is:
Start 4
Start 5
Start 6
Start 1
Start 2
Start 3
End 4
End 3
End 5
End 2
End 1
End 6
What I want is:
Start 4
End 4
Start 5
End 5
Start 6
End 6
Start 1
End 1
Start 2
End 2
Start 3
End 3
EDIT:
I think I’m looking for a task scheduler, similar to QueuedTaskScheduler, that will solve this problem. But any other suggestions are welcome.
The best solution I could find is to make my own version of the
QueuedTaskScheduler(original found in the Parallel Extensions Extras Samples source code).I added a
bool awaitWrappedTasksparameter to the constructors of theQueuedTaskScheduler.I then modified the
ProcessPrioritizedAndBatchedTasks()method to beasyncI then modified the code just after the part where the scheduled task is executed:
The change of method
ThreadBasedDispatchLoopwas a bit different, in that we cannot use theasynckeyword or else we will break the functionality of executing scheduled tasks in the dedicated thread(s). So here is the modified version ofThreadBasedDispatchLoopI have tested this and it gives the desired output. This technique could also be used for any other scheduler. E.g.
LimitedConcurrencyLevelTaskSchedulerandOrderedTaskScheduler