Harmonogram wątków

Każdy wątek ma przypisany priorytet wątku. Wątki utworzone w środowisku uruchomieniowym języka wspólnego są początkowo przypisywane priorytet .ThreadPriority.Normal Wątki utworzone poza środowiskiem uruchomieniowym zachowują priorytet, jaki mieli przed wejściem do środowiska zarządzanego. Możesz uzyskać lub ustawić priorytet dowolnego wątku z właściwością Thread.Priority .

Wątki są zaplanowane do wykonania na podstawie ich priorytetu. Mimo że wątki są wykonywane w środowisku uruchomieniowym, wszystkie wątki są przypisywane wycinki czasu procesora przez system operacyjny. Szczegóły algorytmu planowania używanego do określania kolejności wykonywania wątków różnią się w zależności od systemu operacyjnego. W niektórych systemach operacyjnych wątek o najwyższym priorytcie (z tych wątków, które można wykonać) jest zawsze zaplanowany do pierwszego uruchomienia. Jeśli wszystkie wątki z tym samym priorytetem są dostępne, harmonogram będzie przechodził przez wątki o tym priorytcie, dając każdemu wątkowi stały wycinek czasu, w którym ma zostać wykonany. Jeśli wątki o wyższym priorytcie są dostępne do uruchomienia, wątki o niższym priorytcie nie są wykonywane. Jeśli nie ma więcej wątków możliwych do uruchomienia w danym priorytcie, harmonogram przechodzi do następnego niższego priorytetu i planuje wątki o tym priorytcie na potrzeby wykonywania. Jeśli wątek o wyższym priorytcie staje się uruchamiany, wątek o niższym priorytcie jest wywłaszczony, a wątek o wyższym priorytcie może być wykonywany po raz kolejny. Oprócz tego system operacyjny może również dynamicznie dostosowywać priorytety wątków, ponieważ interfejs użytkownika aplikacji jest przenoszony między pierwszym i tłem. Inne systemy operacyjne mogą zdecydować się na użycie innego algorytmu planowania.

Przykład

Oto przykład wykonywania 9 wątków na wszystkich 5 poziomach priorytetu z Thread.Priority wyliczenia, w którym ostatnie 5 jest na najwyższym poziomie priorytetu. Ponadto mamy obsługę wywołania zwrotnego z poprzedniego artykułu, który w tym kontekście pokazuje, że kolejność inicjowania wątku i priorytetyzacji może nie zawsze być odzwierciedlana w kolejnym kodzie ani w kolejności uruchamiania wykonywania procesów. Oznacza to, że widzimy tutaj równoległy charakter wykonywania kodu i pokaz przypisanych wycinków czasu procesora przez system operacyjny dla każdego wątku. Wyróżnia to wpływ i kontrolę środowiska, w którym działają wątki. W tym przypadku z pewnością widzimy, że wątki o najwyższym priorytcie są rzeczywiście traktowane priorytetowo w wykonaniu.

Poniższy kod spowoduje wygenerowanie dowolnych wyników dla każdego wykonania. Jednak typowe wzorce sekwencji priorytetów, które są uruchamiane, można zaobserwować po wielokrotnym uruchomieniu kodu i przeanalizowaniu danych wyjściowych.

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.
}

Zobacz też