在Huan-Lin學習筆記看到一篇文章 -- C# 學習筆記:多執行緒 (3) - 優先順序。用.NET跑多執行緒對我不算陌生,但卻一直沒注意到.NET的Process跟Thread的Priority是可以調整的。.NET執行緒預設的優先權是Normal,而Windows核心層次的作業(例如滑鼠、鍵盤訊息處理)多半能擁有更高的優先權,無怪乎過去就算寫.NET程式如何搾乾CPU,Windows的基本操作仍能維持順暢。

學到這招讓我動起邪惡的念頭 -- 來寫支可以凍結Windows桌面的.NET程式吧!

做法很簡單,Process及Thread的優先權都拉到最高,一口氣開八條Thread用空轉的while迴圈吃光CPU。為了比較差異,高優先權模式可透過參數決定是否啟動。程式如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
 
namespace SystemHang
{
    class Program
    {
        static void Main(string[] args)
        {
            //由傳入參數決定要不要讓Windows卡卡
            bool freeze = (args.Length > 0 && args[0] == "freeze");
            var p = Process.GetCurrentProcess();
            //卡卡模式時,將Process優先等級拉到RealTime
            //註: 實務上幾乎沒有需要設定RealTime的情境(叔叔有練過,小朋友不要學)
            if (freeze)
                p.PriorityClass = ProcessPriorityClass.RealTime;
            //建立八條Thread,就算i7有四核八緒的也要趕盡殺絕
              Thread[] threads = new Thread[8];
            //使用ManualResetEvent做執行緒同步
              ManualResetEvent[] waits = new ManualResetEvent[threads.Length];
            //設定刑求時間10秒
              DateTime timeUp = DateTime.Now.AddSeconds(10);
            for (int i = 0; i < threads.Length; i++)
            {
                var wait = waits[i] = new ManualResetEvent(false);
                threads[i] = new Thread(() =>
                {
                    //於時限內形成空迴圈,讓條件比對耗盡CPU資源
                    while (DateTime.Now.CompareTo(timeUp) < 0)
                    {
                        //什麼都不做,讓迴圈快速轉動
                    }
                    //通知執行完畢
                    wait.Set();
                });
                //卡卡模式時,指定執行緒優先等級為Highest
                if (freeze)
                    threads[i].Priority = ThreadPriority.Highest;
                //啟動執行緒
                threads[i].Start();
            }
            //等待所有執行緒執行完畢
            WaitHandle.WaitAll(waits);
            Console.WriteLine("Done!");
        }
    }
}

實測結果如下:

程式跑了兩次,執行期間8顆CPU負載全滿,差別在於第一次使用預設優先權,滑鼠還能自由移動,下方的Up Time也如常累計;而第二次將優先權提高後,滑鼠很難移動,而下方的Handles、Threads、Processes、Up Time等統計停止更新,CPU的負載曲線圖表也不動,直到程式結束才恢復。

無聊的小實驗,可以看出優先權高低造成的影響,也由此可知: 除非你有很好的理由,沒事別提高Thread優先權,只會惹人嫌。


Comments

# by 小黑

黑大真是逗趣

# by gattaca

很多設計師都會開Thread, 但是對於共有資源的競爭(例如UI介面的變化)或是執行順序, 都是以 "理想狀況" 去設計, 從未思考是否可歸納為生產者消費者問題, 埋下一堆執行時期的地雷, 請問你如何避免團隊成員亂開Thread?  我目前是規定若有競爭問題必須以這種方式實做www.cnblogs.com/mgen/archive/2012/05/08/2489955.html

# by Jeffrey

to gattaca, 或許是多緒爭奪UI的情境遇得不多,我沒有太多踩到執行期踩地雷的經驗(不過很願意聽你的分享),少數遇到多緒搶餵資料給UI的情況,我傾向在中間加一個Queue,資料提供者塞資料進Queue,UI主動依自己的節奏由Queue抓資料進行更新,概念有一點點接近你提的生產者消費者模式,但沒有Block機制,適用於較簡單的情境。

Post a comment