Заранее извиняюсь за столь длинный вопрос. Разбираюсь c Task
и TaskScheduler
. Я не уверен, что я правильно понимаю смысла существования TaskScheduler
. Как я вижу ситуацию с ним, т.к TaskScheduler
является абстрактным, мы не можем создавать его напрямую, поэтому у нас есть следующие два способа его создания:
TaskScheduler
и переопределить метод QueueTask
который должен запускать задачу отложено;TaskScheduler
с помощью
TaskScheduler.Default
.Потом экземпляр TaskScheduler
мы отправляем в конструктор TaskFactory
и после этого мы на экземпляре TaskFactory
вызывается метод StartNew
, в который мы передаем нашу отложенную задачу. И тут StartNew
вызывает QueueTask
(метод который находится в TaskScheduler
и который мы возможно переопределили) и вот QueueTask
задает отложенный вызов нашей задачи которую мы передали в StartNew
. Вот на основе этого возникли следующие ВОПРОСЫ:
TaskScheduler
вовсе никакой не планировщик задач, а просто прослойка
между запускам задачи и ее началом выполнения. Он просто делает так,
что бы StartNew
(метод TaskFactory
) запускал не саму задачу, а
метод QueueTask
в котором я сам должен сделать всю логику
планирования. Получается он не имеет какую-то внутреннюю логику по
запуску задач отложено. Нет, я понимаю, он имеет потому, что я сам
ее написал в методе QueueTask
, но по факту TaskScheduler
это лишь
механизм внедрения МОЕГО собственного планировщика. Я правильно
понимаю или же я чего-то не знаю?TaskScheduler
через TaskScheduler.Default
какая
реализация будет у QueueTask
? Как я понял он просто сразу запускает
задачу...ThreadPool.RegisterWaitForSingleObject
т.е все, мы отправили туда callback. Второй раз мы уже не можем
запустить эту задачу, зачем нам ее хранить? Я лишь предполагаю, что
мы ее храним лишь для возможного контроля ее, до запуска.Task
-- это абстракция задачи, которая
ничего не говорит о том, где и кем будет выполнена задача. Этим как
раз управляет TaskScheduler
. Как вы верно заметили, класс
TaskScheduler
является абстрактным, а значит, конкретная логика
заключена в его наследниках. А вот TaskFactory
(и метод
Task.Run()
) -- это действительно прослойка между задачей и
планировщиком.TaskScheduler.Default
. Это
планировщик пула потоков. Он выполняет порученные задачи в
потоках из пула потоков. Время старта задачи при этом никак не
оговаривается. Второй пример -- это группа планировщиков, которые
предоставляет текущий синхронизационный контекст --
TaskScheduler.FromCurrentSynchronizationContext
(например,
ASP.NET, WinForms или WPF). Соответственно задача, которая была
передана, например, планировщику WinForms, будет выполнена в главном
(UI) потоке.P.S. В 99% случаев достаточно вызывать Task.Run()
и не связываться с TaskFactory
.
Для начала, параллельно к TaskScheduler.Default
есть ещё TaskScheduler.FromCurrentSynchronizationContext()
(который в главном потоке WPF и WinForms создают scheduler, выполняющий задания в этом самом потоке). Кроме того, использовать TaskScheduler
можно и в других местах, например, в Task.ContinueWith
, ну и await
тоже пользуется им под капотом.
Можно смотреть на TaskScheduler
как на «прослойку» между отправкой таска на выполнение и самим выполнением. Но это собственно и есть смысл «планировки»: вы поставляете таск, а как и когда он будет запущен — вопрос, который решает планировщик (scheduler). То есть TaskScheduler
— это не механизм внедрения вашего планировщика, это и есть планировщик!
Получается он не имеет какую-то внутреннюю логику по запуску задач отложено
Не получается. Ваш метод QueueTask
— часть TaskScheduler
'а, это и есть вызов внутренней логики по запуску задач!
Если я создам TaskScheduler
через TaskScheduler.Default
какая реализация будет у QueueTask
TaskScheduler.Default
— планировщий на пуле потоков. Он просто выполнит ThreadPool.QueueUserWorkItem
.
Из исходников .NET:
protected internal override void QueueTask(Task task)
{
if ((task.Options & TaskCreationOptions.LongRunning) != 0)
{
// Run LongRunning tasks on their own dedicated thread.
Thread thread = new Thread(s_longRunningThreadWork);
thread.IsBackground = true; // Keep this thread from blocking process shutdown
thread.Start(task);
}
else
{
// Normal handling for non-LongRunning tasks.
bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0);
ThreadPool.UnsafeQueueCustomWorkItem(task, forceToGlobalQueue);
}
}
В примерах с QueueTask кроме отложенного запуска задачи делают добавление этой задачи в очередь... Зачем?
Это нужно спрашивать у авторов примера — скорее всего, в коде примера видно, откуда ещё производится доступ к очереди. ThreadPoolTaskScheduler
, например, в QueueTask
ничего не добавляет.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Использую awesomium вместо стандартного компонента браузераНужно изменить user agent
Нужно достать параметры некоторого объекта изdwg файла