C#語法基礎-04-線程

C#語法基礎-04-線程

寫這兩篇文章的目的是爲了備忘、 C#語言在大學讀書時候學過、當時做過一些東西、但是由於從事的主要工作和C#無關便忘記了。 近來公司增加了Unity業務、 寫Unity主要是C# 和js 想來C# 的語法結構和Java很相似、於是採用了C#語言作爲公司遊戲項目的主要語言。

本系列主要分上中下三篇文章來記錄。 分別牽涉到C# 中的初級、中級、高級內容。

由於本月一直忙於公司的項目、 所以發文就耽擱了, 但是回想五月忙上過去了,還是整理整理髮一篇吧。

本文主要寫一些關於C#語言的高級知識, 如果沒有看過初級的,可以先看上一篇文章,在電腦上敲敲試試,跑一下看看。

  1. 委託方式發起線程

namespace _01_線程_委託方式發起線程 {
    class Program {
        //一般我們會爲比較耗時的操作 開啓單獨的線程去執行,比如下載操作
        static int Test(int i,string str)
        {
            Console.WriteLine("test"+i+str);
            Thread.Sleep(100);//讓當親線程休眠(暫停線程的執行) 單位ms
            return 100;
        }
        static void Main(string[] args) {//在main線程中執行 一個線程裏面語句的執行 是從上到下的
            //1,通過委託 開啓一個線程
            //Func<int, string, int> a = Test;
            //IAsyncResult ar = a.BeginInvoke(100, "siki", null, null);// 開啓一個新的線程去執行 a所引用的方法 

            ////IAsyncResult 可以取得當前線程的狀態
            ////可以認爲線程是同時執行的(異步執行)
            //Console.WriteLine("main");
            //while (ar.IsCompleted == false)//如果當前線程沒有執行完畢
            //{
            //    Console.Write(".");
            //    Thread.Sleep(10); //控制子線程的檢測頻率
            //}
            //int res = a.EndInvoke(ar);//取得異步線程的返回值
            //Console.WriteLine(res);


            //檢測線程結束
            //bool isEnd = ar.AsyncWaitHandle.WaitOne(1000);
            //1000毫秒錶示超時時間,如果等待了1000毫秒 線程還沒有結束的話 那麼這個方法會返回false 如果在1000毫秒以內線程結束了,那麼這個方法會返回true
            //if (isEnd)
            //{
            //    int res  = a.EndInvoke(ar);
            //    Console.WriteLine(res);
            //}

            //通過回調 檢測線程結束
            //Func<int, string, int> a = Test;
            //倒數第二個參數是一個委託類型的參數,表示回調函數,就是當線程結束的時候會調用這個委託指向的方法 倒數第一個參數用來給回調函數傳遞數據
            //IAsyncResult ar = a.BeginInvoke(100, "siki", OnCallBack, a);// 開啓一個新的線程去執行 a所引用的方法 
            //a.BeginInvoke(100, "siki", ar =>
            //{
            //    int res = a.EndInvoke(ar);
            //    Console.WriteLine(res+"在lambda表達式中取得");
            //}, null);

            Console.ReadKey();
        }

        static void OnCallBack( IAsyncResult ar )
        {
            Func<int, string, int> a = ar.AsyncState as Func<int, string, int>;
            int res =  a.EndInvoke(ar);
            Console.WriteLine(res+"在回調函數中取得結果");
        }
    }
}

  1. 通過Thread發起線程

namespace _02_線程_通過Thread發起線程 {
    class Program {
        static void DownloadFile(object filename)
        {
            Console.WriteLine("開始下載:"  +Thread.CurrentThread.ManagedThreadId +filename);
            Thread.Sleep(2000);
            Console.WriteLine("下載完成");

        }
        static void Main(string[] args) {
            //Thread t = new Thread(DownloadFile);//創建出來Thread對象,這個線程並沒有啓動
            //t.Start();//開始,開始去執行線程
            //Console.WriteLine("Main");

            //Thread t = new Thread(() =>
            //{
            //    Console.WriteLine("開始下載:" + Thread.CurrentThread.ManagedThreadId);
            //    Thread.Sleep(2000);
            //    Console.WriteLine("下載完成");
            //});
            //t.Start();


            //Thread t = new Thread(DownloadFile);//創建出來Thread對象,這個線程並沒有啓動
            //t.Start("xxx.種子");//開始,開始去執行線程
            //Console.WriteLine("Main");

            //MyThread my = new MyThread("xxx.bt","http://www.xxx.bbs");
            //Thread t = new Thread(my.DownFile);//我們構造一個thread對象的時候,可以傳遞一個靜態方法,也可以傳遞一個對象的普通方法
            //t.Start();

            //Thread t = new Thread(DownloadFile);//這個是前臺線程
            Thread t = new Thread(DownloadFile);//這個是前臺線程
            //t.IsBackground = true;//設置爲後臺線程 
            t.Start("xx");
            //t.Abort();//終止這個線程的執行
            t.Join();//噹噹前線程睡眠,等待t線程執行完,然後繼續運行下面的代碼
            //
        }
    }
}

 class MyThread
    {
        private string filename;
        private string filepath;

        public MyThread(string fileName, string filePath)
        {
            this.filename = fileName;
            this.filepath = filePath;
        }

        public void DownFile()
        {
            Console.WriteLine("開始下載"+filepath+filename);
            Thread.Sleep(2000);
            Console.WriteLine("下載完成");
        }

    }
    

3.線程池


namespace _03_線程_線程池 {
    class Program {
        static void ThreadMethod(object state)
        {
            Console.WriteLine("線程開始:"+Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
            Console.WriteLine("線程結束");
        }
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(ThreadMethod);//開啓一個工作線程
            ThreadPool.QueueUserWorkItem(ThreadMethod);
            ThreadPool.QueueUserWorkItem(ThreadMethod);
            ThreadPool.QueueUserWorkItem(ThreadMethod);
            ThreadPool.QueueUserWorkItem(ThreadMethod);
            ThreadPool.QueueUserWorkItem(ThreadMethod);
            ThreadPool.QueueUserWorkItem(ThreadMethod);
            Console.ReadKey();

        }
    }
}

4.線程任務


namespace _04_線程_任務 {
    class Program {
        static void ThreadMethod() {
            Console.WriteLine("任務開始");
            Thread.Sleep(2000);
            Console.WriteLine("任務結束");
        }
        static void Main(string[] args) {
            //Task t = new Task(ThreadMethod);//傳遞一個需要線程去執行的方法
            //t.Start();

            //TaskFactory tf = new TaskFactory();
            //Task t = tf.StartNew(ThreadMethod);

            Console.WriteLine("Main");
            Console.ReadKey();
        }
    }
}

5.線程爭用問題


namespace _05_線程問題_爭用條件 {
    class Program {
        static void ChangeState(object o)
        {
            MyThreadObject m = o as MyThreadObject;
            while (true)
            {
                lock (m)//向系統申請可不可以 鎖定m對象 如果m對象沒有被鎖定,那麼可以 如果m對象唄鎖定了,那麼這個語句會暫停,知道申請到m對象
                {
                    m.ChangeState();//在同一時刻 只有一個線程在執行這個方法
                }//釋放對m的鎖定
                
            }
        }
        static void Main(string[] args) {
            MyThreadObject m = new MyThreadObject();
            Thread t = new Thread(ChangeState);
            t.Start(m);

            new Thread(ChangeState).Start(m);

            Console.ReadKey();
        }
    }
}

  1. 總結

還是那句話、多思考、上手敲代碼、 調試調試、多試試。 如果有問題可以評論區留言共同學習進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章