Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Каждому потоку назначается определенный приоритет. Потокам, созданным в общеязыковой среде выполнения, изначально назначается приоритет ThreadPriority.Normal. Потоки, созданные за пределами среды выполнения, сохраняют приоритет, который они имели до входа в управляемую среду. Вы можете получить или задать приоритет для любого потока, используя свойство Thread.Priority.
Потоки планируются для выполнения, учитывая их приоритеты. Несмотря на то, что потоки выполняются в среде выполнения, процессорное время им выделяет операционная система. Сведения о алгоритме планирования, используемом для определения порядка выполнения потоков, зависят от каждой операционной системы. В некоторых операционных системах первым всегда выполняется поток с наивысшим приоритетом (из числа тех потоков, которые готовы к выполнению). Если доступны несколько потоков с одинаковым приоритетом, планировщик поочередно запускает все потоки с этим приоритетом, выделяя каждому фиксированное время для выполнения. Пока есть хоть один доступный для выполнения поток с более высоким приоритетом, ни один из потоков с более низким приоритетом не запускается. Когда не останется ни одного готового потока с этим приоритетом, планировщик назначает для выполнения потоки со следующим, более низким, приоритетом. Если поток с более высоким приоритетом становится готовым к выполнению, поток с более низким приоритетом прерывается, и потоку с более высоким приоритетом позволено выполняться снова. Кроме того, операционная система может динамически изменять приоритеты потоков при перемещении пользовательского интерфейса приложения на передний план или в фоновый режим. Другие операционные системы могут использовать другой алгоритм планирования.
Пример
Ниже приведен пример выполнения 9 потоков на всех 5 уровнях приоритета из Thread.Priority перечисления, из них последние 5 находятся на самом высоком уровне приоритета. Кроме того, у нас есть поддержка обратного вызова из предыдущей статьи, что в этом контексте демонстрирует, что порядок инициализации и приоритезации потоков может не всегда отражаться в последующем коде или не соблюдаться порядок запуска процессов. Это означает, что здесь мы видим параллельную природу выполнения кода и демонстрацию назначенных срезов времени процессора операционной системой для каждого потока. Это подчеркивает влияние и управление средой, в которой выполняются потоки. С этим мы, безусловно, видим, что наиболее приоритетные потоки действительно получают приоритет в выполнении.
Следующий код создает произвольные результаты для каждого выполнения. Однако распространенные шаблоны последовательности запускаемых приоритетов можно наблюдать после выполнения кода несколько раз и анализа выходных данных.
namespace snippets;
public class SchedulingThreads
{
public void RunMultipleThreadsOnDifferentPriorities()
{
var threadsList = new List<Thread>(9);
// Initialize 9 threads. 5 with Highest priority, and the first 4 from Lowest to Normal range.
for (int i = 0; i < 9; i++)
{
var thread = new Thread(() => { new ThreadWithCallback(Callback).Process(); });
if (i > 3)
thread.Priority = ThreadPriority.Highest;
else
thread.Priority = (ThreadPriority)i;
threadsList.Add(thread);
}
threadsList.ForEach(thread => thread.Start());
}
public void Callback(ThreadPriority threadPriority)
{
Console.WriteLine($"Callback in {threadPriority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
}
public class ThreadWithCallback
{
public ThreadWithCallback(Action<ThreadPriority> callback)
{
this.callback = callback;
}
public Action<ThreadPriority> callback;
public void Process()
{
Console.WriteLine($"Entered process in {Thread.CurrentThread.Priority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
Thread.Sleep(1000);
Console.WriteLine($"Finished process in {Thread.CurrentThread.Priority} priority. \t\t ThreadId: {Thread.CurrentThread.ManagedThreadId}.");
if (callback != null)
{
callback(Thread.CurrentThread.Priority);
}
}
}
// The example displays the output like the following:
// Entered process in Highest priority. ThreadId: 9.
// Entered process in Highest priority. ThreadId: 12.
// Entered process in Normal priority. ThreadId: 6.
// Entered process in BelowNormal priority. ThreadId: 5.
// Entered process in Lowest priority. ThreadId: 4.
// Entered process in AboveNormal priority. ThreadId: 7.
// Entered process in Highest priority. ThreadId: 11.
// Entered process in Highest priority. ThreadId: 10.
// Entered process in Highest priority. ThreadId: 8.
// Finished process in Highest priority. ThreadId: 9.
// Finished process in Highest priority. ThreadId: 12.
// Finished process in Highest priority. ThreadId: 8.
// Finished process in Highest priority. ThreadId: 10.
// Callback in Highest priority. ThreadId: 10.
// Finished process in AboveNormal priority. ThreadId: 7.
// Callback in AboveNormal priority. ThreadId: 7.
// Finished process in Lowest priority. ThreadId: 4.
// Callback in Lowest priority. ThreadId: 4.
// Finished process in Normal priority. ThreadId: 6.
// Callback in Highest priority. ThreadId: 9.
// Callback in Highest priority. ThreadId: 8.
// Callback in Highest priority. ThreadId: 12.
// Finished process in Highest priority. ThreadId: 11.
// Callback in Highest priority. ThreadId: 11.
// Callback in Normal priority. ThreadId: 6.
// Finished process in BelowNormal priority. ThreadId: 5.
// Callback in BelowNormal priority. ThreadId: 5.
}