İş parçacıklarını zamanlama

Her iş parçacığına atanmış bir iş parçacığı önceliği vardır. Ortak dil çalışma zamanı içinde oluşturulan iş parçacıklarına başlangıçta önceliği ThreadPriority.Normalatanır. Çalışma zamanı dışında oluşturulan iş parçacıkları, yönetilen ortama girmeden önce sahip oldukları önceliği korur. özelliğiyle Thread.Priority herhangi bir iş parçacığının önceliğini alabilir veya ayarlayabilirsiniz.

İş parçacıkları, önceliklerine göre yürütülmeye zamanlanır. İş parçacıkları çalışma zamanı içinde yürütülse de, tüm iş parçacıklarına işletim sistemi tarafından işlemci zaman dilimleri atanır. İş parçacıklarının yürütüleceği sırayı belirlemek için kullanılan zamanlama algoritmasının ayrıntıları her işletim sistemine göre değişir. Bazı işletim sistemlerinde, en yüksek önceliğe sahip iş parçacığı (yürütülebilen iş parçacıklarından) her zaman önce çalışacak şekilde zamanlanır. Aynı önceliğe sahip birden çok iş parçacığının tümü kullanılabilir durumdaysa, zamanlayıcı iş parçacıkları arasında bu önceliğe göre döngü gerçekleştirerek her iş parçacığına yürütülecek sabit bir zaman dilimi verir. Daha yüksek önceliğe sahip bir iş parçacığı çalıştırılmaya hazır olduğu sürece, düşük öncelikli iş parçacıkları yürütülür. Belirli bir önceliğe sahip daha fazla çalıştırılabilir iş parçacığı olmadığında, zamanlayıcı bir sonraki düşük önceliğe geçer ve yürütme için iş parçacıklarını bu önceliğe zamanlar. Daha yüksek öncelikli bir iş parçacığı çalıştırılabilir hale gelirse, düşük öncelikli iş parçacığı önlenir ve daha yüksek öncelikli iş parçacığının bir kez daha yürütülmesine izin verilir. Tüm bunların yanı sıra, bir uygulamanın kullanıcı arabirimi ön plan ve arka plan arasında taşındığından işletim sistemi iş parçacığı önceliklerini dinamik olarak da ayarlayabilir. Diğer işletim sistemleri farklı bir zamanlama algoritması kullanmayı seçebilir.

Örnek

Burada, son 5'in en yüksek öncelik düzeyinde olduğu numaralandırmadan 5 öncelik düzeyinin Thread.Priority tamamından 9 iş parçacığı yürütme örneği verilmiştir. Ayrıca, bu bağlamda iş parçacığı başlatma ve öncelik belirleme sırasının her zaman sonraki koda yansıtılmayabileceğini veya yürütmeleri başlatma sırasının her zaman yansıtılmayabileceğini gösteren önceki makaleden geri çağırma desteğine sahibiz. Yani burada kod yürütmenin paralel niteliğini ve her iş parçacığı için işletim sistemi tarafından atanan işlemci zamanı dilimlerinin gösterimini görüyoruz. Bu, iş parçacıklarının çalıştığı ortamın etkisini ve denetimini vurgular. Bununla birlikte, en yüksek öncelikli iş parçacıklarının yürütmede gerçekten öncelik aldığını kesinlikle görüyoruz.

Aşağıdaki kod her yürütmede rastgele sonuçlar üretir. Ancak, kodu birden çok kez çalıştırdıktan ve çıkışlar çözümlendikten sonra çalıştırılan önceliklerin ortak sıra desenleri gözlemlenebilir.

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

Ayrıca bkz.