When using `Task.Run(...)` with C#, it will run tasks on the main thread if all other threads are busy. This means at high workloads, the main thread will slow down. For games that want to keep the main thread light, this is an issue.
C# allows your to customise which threads can run tasks, by overriding the `TaskScheduler` class. So I created a custom class and set `MaximumConcurrencyLevel` to the number of threads minus one. This prevents tasks from running on the main thread.
To use this custom scheduler, you'll need to use the [[TaskHelper]] class, instead of `Task.Run()`, i.e:
```cs
// This is good!
VETask task = TaskHelper.Run(() =>
{
Console.WriteLine("This code will never run on the main thread");
});
// This is not good!
Task task = Task.Run(() =>
{
Console.WriteLine("This code might run on the main thread");
});
```
`TaskHelper.Run` returns a [[VETask]], which is a wrapper around a regular `Task` object. The main difference is it stores a `CompletionHandled` field, which indicates whether your code has handled the completion of this task. This prevents handling the completion of a task twice.
```cs
VETask task;
void Startup()
{
task = TaskHelper.Run(() =>
{
// Do some work...
});
}
void OnFrame()
{
if (TaskHelper.JustCompleted(task))
{
// This runs once when a task initially completes
}
if (TaskHelper.Completed(task))
{
// This runs every frame, after the task has completed
}
}
```
## Debugging
For debugging / profiling reasons you may want to run everything on the main thread, so it's easier to keep track of the order that code runs. To do this, set this field to true:
```cs
TaskHelper.RunEverythingSinglethreaded = true;
```