Thread 與 ThreadPool class example

 

一、Thread

1、範例一

using System;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread tTom = new Thread(TomToRun);
            Thread tBill = new Thread(BillToRun);

            tTom.Start();
            tBill.Start();

            Console.ReadKey();
        }

        public static void TomToRun()
        {
            for (int i = 0; i <= 10; i++)
            {
                Console.WriteLine("Tom Run: {0} meter", i);
            }
        }

        public static void BillToRun()
        {
            for (int i = 0; i <= 10; i++)
            {
                Console.WriteLine("Bill Run: {0} meter", i);
            }
        }

    }

}

在 CPU 四核心的執行畫面為:

在 CPU 單核心的執行畫面為:

說明:

a、在程式碼上,由於是 tTom 先開始跑的,之後 tBill 也跟著跑,

所以畫面上一定會是第一個出現「Tom Run: 0 meter」訊息,而不是「Bill Run: 0 meter」訊息。

 

2、範例二、使用 join 方法,讓其執行完全跑完,才可以讓別的執行緒跑

using System;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread tTom = new Thread(TomToRun);
            Thread tBill = new Thread(BillToRun);

            tTom.Start();
            tTom.Join();
            tBill.Start();

            Console.ReadKey();
        }

        public static void TomToRun()
        {
            for (int i = 0; i <= 10; i++)
            {
                Console.WriteLine("Tom Run: {0} meter", i);
            }
        }

        public static void BillToRun()
        {
            for (int i = 0; i <= 10; i++)
            {
                Console.WriteLine("Bill Run: {0} meter", i);
            }
        }

    }

}

執行畫面為:

 

3、其他範例

using System;
using System.Threading;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main thread: Start a second thread.");
            // The constructor for the Thread class requires a ThreadStart 
            // delegate that represents the method to be executed on the 
            // thread.  C# simplifies the creation of this delegate.
            Thread t = new Thread(ThreadProc);

            // Start ThreadProc.  Note that on a uniprocessor, the new 
            // thread does not get any processor time until the main thread 
            // is preempted or yields.  Uncomment the Thread.Sleep that 
            // follows t.Start() to see the difference.
            t.Start();
            Thread.Sleep(0);

            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("Main thread: Do some work. " + i);
                Thread.Sleep(0);
            }

            Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
            t.Join();
            Console.WriteLine("Main thread: ThreadProc.Join has returned.  Press Enter to end program.");

            Console.ReadKey();
        }

        public static void ThreadProc()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("ThreadProc: {0}", i);
                // Yield the rest of the time slice.
                Thread.Sleep(0);
            }
        }
    }
}

說明:

a、寫法 Thread t = new Thread(ThreadProc); 或是

Thread t = new Thread(new ThreadStart(ThreadProc)); 寫法,都是一樣的。

 

二、ThreadPool

using System;
using System.Threading;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            // Queue the task.
            ThreadPool.QueueUserWorkItem(ThreadProc);
            Console.WriteLine("Main thread {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(1000);

            Console.WriteLine("exits. {0}", Thread.CurrentThread.ManagedThreadId);

            Console.ReadKey();
        }

        static void ThreadProc(Object stateInfo)
        {
            // No state object was passed to QueueUserWorkItem, so stateInfo is null.
            Console.WriteLine("ThreadProc {0}", Thread.CurrentThread.ManagedThreadId);
        }
    }
}

說明:

ThreadPool.QueueUserWorkItem(ThreadProc); 和

Console.WriteLine("Main thread {0}", Thread.CurrentThread.ManagedThreadId);

會有同等優先權,也就是說兩者都有機會搶第一先被執行。

 

三、總結

1、Thread 與 ThreadPool 在 .NET framework 1.1 就有提供了,看來真的有歷史耶。

2、Thread 與 ThreadPool 無法得知執行緒工作何時完成,以及當工作完成時也無法取得其執行結果。

3、I/O-Bound 適用多執行緒處理,CPU-Bound 適用非同步處理。

 

參考資料:

Thread Class

ThreadPool Class

Threading in C#, by Joe Albahari