2012-02-29 4 views
4

У моего ноутбука есть 2 логических процессора, и я наткнулся на сценарий, где, если я планирую 2 задачи, которые занимают больше 1 секунды, не обозначая их долговременными, последующие задачи запускаются через 1 секунду. Можно ли изменить этот тайм-аут?Почему в параллельной библиотеке задач есть «скрытый» 1-й тайм-аут для планирования задач при определенных условиях?

Я знаю, что нормальные задачи должны быть кратковременными - гораздо короче, чем когда-либо, - возможно, мне просто интересно, что я вижу жестко закодированное поведение TPL или могу повлиять на это поведение иначе, -Бег.

метод

Это приложение консоли должно продемонстрировать поведение для машины с любым количеством процессоров:

static void Main(string[] args) 
{ 
    var timer = new Stopwatch(); 
    timer.Start(); 

    int numberOfTasks = Environment.ProcessorCount; 

    var rudeTasks = new List<Task>(); 
    var shortTasks = new List<Task>(); 

    for (int index = 0; index < numberOfTasks; index++) 
    { 
     int capturedIndex = index; 
     rudeTasks.Add(Task.Factory.StartNew(() => 
     { 
      Console.WriteLine("Starting rude task {0} at {1}ms", capturedIndex, timer.ElapsedMilliseconds); 
      Thread.Sleep(5000); 
     })); 
    } 

    for (int index = 0; index < numberOfTasks; index++) 
    { 
     int capturedIndex = index; 
     shortTasks.Add(Task.Factory.StartNew(() => 
     { 
      Console.WriteLine("Short-running task {0} running at {1}ms", capturedIndex, timer.ElapsedMilliseconds); 
     })); 
    } 

    Task.WaitAll(shortTasks.ToArray()); 
    Console.WriteLine("Finished waiting for short tasks at {0}ms", timer.ElapsedMilliseconds); 

    Task.WaitAll(rudeTasks.ToArray()); 
    Console.WriteLine("Finished waiting for rude tasks at {0}ms", timer.ElapsedMilliseconds); 

    Console.ReadLine(); 
} 

Здесь выводится для приложения на моем 2 Proc ноутбук:

Starting rude task 0 at 2ms 
Starting rude task 1 at 2ms 
Short-running task 0 running at 1002ms 
Short-running task 1 running at 1002ms 
Finished waiting for short tasks at 1002ms 
Finished waiting for rude tasks at 5004ms 

Press any key to continue . . . 

строки:

Short-running task 0 running at 1002ms 
Short-running task 1 running at 1002ms 

указывает, что существует тайм-аут в 1 секунду или что-то в этом роде, позволяющее более короткие задачи для планирования по «грубым» задачам. Об этом я и спрашиваю.

+0

Пожалуйста, пост описание проступка. –

+0

@AdamRobinson Привет, Адам, первый абзац описывает поведение, которое я вижу, - я не уверен, если я буду называть это «неправильным поведением», но я хотел бы знать, могу ли я каким-либо образом повлиять на это поведение или мне нужно настроить мои ожидания и подход к использованию TPL – ZeroBugBounce

+0

К сожалению, я имел в виду примерный вывод, демонстрирующий то, что вы описываете. Я не совсем понимаю, что вы описываете, но просмотр вашего консольного вывода может сделать это более ясным. –

ответ

4

Поведение, которое вы видите, не относится к TPL, оно относится к TPL's default scheduler. Планировщик пытается увеличить количество потоков, так что те, которые работают, не «выкапывают» процессор и не заглушают других. Также полезно избегать ситуаций тупиковой ситуации, если два запускаются и ждут самих Заданий.

Если вы хотите изменить режим планирования, вы можете посмотреть в implementing your own TaskScheduler.

4

Это стандартное поведение для планировщика потока. Он пытается сохранить количество активных потоков равным количеству ядер. Но не может делать работу очень хорошо, когда ваши задачи делают много блокировки, а не работают. Сон в вашем случае. Дважды в секунду он позволяет запускать другой поток, чтобы попытаться сработать отставание. Похоже, у вас двухъядерный процессор.

Правильное обходное решение - использовать TaskCreationOptions.LongRunning, поэтому планировщик использует обычный поток вместо потока threadpool. Неправильное обходное решение - использовать ThreadPool.SetMinThreads. Но вы, возможно, должны сосредоточиться на выполнении реальной работы в своих задачах, Sleep() не очень хорошая имитация этого.

1

Проблема заключается в том, что планировщик запускает новые задачи, когда пытается определить, длится ли задание. Вы можете сказать, что TPL задача давно работает в качестве параметра задачи:

for (int index = 0; index < numberOfTasks; index++) 
{ 
    int capturedIndex = index; 
    rudeTasks.Add(Task.Factory.StartNew(() => 
    { 
     Console.WriteLine("Starting rude task {0} at {1}ms", capturedIndex, timer.ElapsedMilliseconds); 
     Thread.Sleep(3000); 
    }, TaskCreationOptions.LongRunning)); 
} 

Результирующее в:

Starting rude task 0 at 11ms 
Starting rude task 1 at 13ms 
Starting rude task 2 at 15ms 
Starting rude task 3 at 19ms 
Short-running task 0 running at 45ms 
Short-running task 1 running at 45ms 
Short-running task 2 running at 45ms 
Short-running task 3 running at 45ms 
Finished waiting for short tasks at 46ms 
Finished waiting for rude tasks at 3019ms 
Смежные вопросы