Ответ 1
RunSynchronously
делегирует решение о том, когда начинать задачу, текущему планировщику задач (или переданному в качестве аргумента).
Я не уверен, почему он существует (может быть, для внутреннего или устаревшего использования), но трудно представить себе полезный вариант использования в текущих версиях .NET. У @Fabjan есть возможное объяснение в его комментарии к вопросу.
RunSynchronously
просит планировщик запустить его синхронно, но тогда планировщик вполне может проигнорировать подсказку и запустить его в потоке пула потоков, и ваш текущий поток будет синхронно блокироваться до его завершения.
Планировщик не должен запускать его в текущем потоке и не должен запускать его немедленно, хотя я думаю, что это произойдет с обычными планировщиками (ThreadPoolTaskScheduler и обычными планировщиками пользовательского интерфейса).
RunSynchronously
также вызовет исключение, если задача уже была запущена или завершена/не выполнена (это означает, что вы не сможете использовать ее в асинхронных методах).
Этот код может прояснить другое поведение:
Wait
и Result
вообще не запускают задачу, они просто ждут завершения задачи в текущем потоке и блокируют его до завершения, поэтому, если мы хотим сравнить, мы можем сравнить Start
и Wait
с RunSynchronously
:
class Scheduler : TaskScheduler
{
protected override void QueueTask(Task task) =>
Console.WriteLine("QueueTask");
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
Console.WriteLine("TryExecuteTaskInline");
return false;
}
protected override IEnumerable<Task> GetScheduledTasks() => throw new NotImplementedException();
}
static class Program
{
static void Main()
{
var taskToStart = new Task(() => { });
var taskToRunSynchronously = new Task(() => { });
taskToStart.Start(new Scheduler());
taskToRunSynchronously.RunSynchronously(new Scheduler());
}
}
Если вы попытаетесь комментировать Start или RunSynchronously
и запустите код, вы увидите, что Start
попытается поставить задачу в очередь в планировщике, а RunSynchronously
попытается выполнить ее в оперативном режиме, а в случае неудачи (вернет false) она просто поставит ее в очередь.