.Net 多線程編程由淺入深知識梳理

1.Using System.Threading;
     多線程就是一個包工頭,讓手底下的十個工人去搬磚頭的事兒。
    
------------不帶任何傳入參數的Thread
2.ThreadStart ts = new ThreadStart(某線程A的Func);
   Thread th = new Thread(ts);
   th.Start();
   
   public void 某線程A的Func()
   {
        Console.WriteLine("線程A把事情作好了!");
        Console.ReadKey();
   }
   
   原理解析
   2.1 ThreadStart原型爲一個委託類型:
         public delegate void ThreadStart();
   2.2 ThreadStart這個委託類型是沒有任何傳入參數的
   
   以下可讓ThreadStart可以接收參數
    public class MyThread
    {
        private double _width = 10.0;
        private double _height = 9.0;
        private double result = 0.0;
        public MyThread(double width,double height)
        {
            this._width = width;
            this._height = height;
        }

        public void MyThreadExc()
        {
            Console.WriteLine("MyThread Execute Start ...");
            Thread.Sleep(2000);
            result = _width * _height;
            Console.WriteLine("MyThread Execute Done:The Result is {0}", result);
        }
    }
    
    static void Main(string[] args)
    {
        MyThread th = new MyThread(5.0,3.0);
        Thread t = new Thread(new ThreadStart(th.MyThreadExc));
        t.Start();
        Console.ReadKey();
    }
   
         
 ------------帶有參數的Thread
 3.ParameterizedThreadStart pts = new  ParameterizedThreadStart(某線程B的Func);
    Thread th = new Thread(pts);
    th.Start(objParam);
    
    public void 某線程B的Func(object param)
    {
         Console.WriteLine("線程B接收了param並把事情作好了!");
    }
    
    原理解析
    3.1 ParameterizedThreadStart原型爲一個委託類型:
         public delegate void ParameterizedThreadStart(object obj);
    3.2 ParameterizedThreadStart這個委託類型是接收Object傳參的
    
------------帶有傳入參數而且有返回參數
 剛纔說到主線程須要知道子線程何時執行完成,咱們能夠用Thread.ThreadState枚舉來進行判斷
 當線程的ThreadState==Thread.Stop時,此時就能夠判斷該Thread已經結束,這時它的結果就可使用了,若是不是這個狀態,就繼續執行別的工做,或等待再次嘗試。假若須要有多個子
 線程返回,而且須要他們的返回內容再進行異步計算,這就叫作線程同步了,下面將介紹一種方法,可以自定義參數個數,而且返回數據,使用起來很方便
 使用委託的異步調用方法和回調
 1. 須要異步調用的Func定義爲一個委託
 2. BeginInvoke來異步調用 -- 第一個參數是傳參,第二個參數是當線程執行完畢以後調用的方法 (穿插複習Invoke 與 BeginInvoke的區別)
 
 delegate double MyJobDelegate(double d);

 static  MyJobDelegate myJob;
 
 double jobResult=0.0;
 
 static void Main(string[] args)
 {
     myJob = new MyJobDelegate(Job1);
     myJob.BeginInvoke(5.09,new AsyncCallback(Job1Done),null)
 }
 
 static double Job1(double d)
 {
     return d*Math.PI;
 }
 
 static void Job1Done(IAsyncResult result)
 {
     Console.WriteLine(myJob.EndInvoke(result));
 }
 
 Asynchronous 異步
 Synchronous  同步
 [在C#中使用線程的方法不少,使用委託的BeginInvoke和EndInvoke方法就是其中之一。BeginInvoke方法可使用線程異步地執行委託所指向的方法。而後經過EndInvoke方法得到方法的返回值
 (EndInvoke方法的返回值就是被調用方法的返回值),或是肯定方法已經被成功調用。]
 
 -------------線程池
 線程雖然是個好東西,可是也是一個資源消耗大戶,咱們須要用多線程,可是又不但願線程過多,線程池的機制就應運而生啦,.Net爲咱們提供了一個現成的ThreadPool,他的使用以下:
 
 ///
 ///首先下面這是線程池線程所要執行的回調方法
 ///
using System;
using System.Runtime.InteropServices;

namespace System.Threading
{
    // 摘要:
    //     表示線程池線程要執行的回調方法。
    //
    // 參數:
    //   state:
    //     包含回調方法要使用的信息的對象。
    [ComVisible(true)]
    public delegate void WaitCallback(object state);
}

static WaitCallback wait;

static void Main(string[] args)
{
    wait = new WaitCallback(myJob);
    ThreadPool.QueueUserWorkItem(wait,1.0);
    ThreadPool.QueueUserWorkItem(wait,2.0);
    ThreadPool.QueueUserWorkItem(wait,3.0);
    ThreadPool.QueueUserWorkItem(wait,4.0);
    Console.ReadKey();
}

private static void myJob(object obj)
{
    double d= (double)obj;
    Console.WriteLine("Job Exec Result: {0}",d*Math.PI);
}


-------------控制權
場景:若是Winfrom程式主線程建立了一個控件TextBox1,隨後某個子線程開始建立而且工做,產生一個返回值,若是此時將該返回值返回給TextBox1,程式就會報錯:禁止跨線程訪問控件;
那麼此時咱們就須要用到控件的一個方法:BeginInvoke或Invoke,這個方法能夠把執行上下文切換回建立這個控件的線程:
delegate void ChangeTextBoxDelegate(string newtext);

private void Button1_Click(object sender,EventArgs e)
{
    ParameterizedThreadStart pts = new ParameterizedThreadStart(myJob);
    Thread th = new Thread(pts);
    th.Start(1.09);
}

----------------方案1---------------
private void myJob(object obj)
{
    this.BeginInvoke(new ChangeTextBoxDelegate(this.TextBox1.AppendText)),((double)obj * Math.PI).ToString());
}


    或者 (推薦)
----------------方案2--------------
    private void SetTextBox1Text(string text)
    {
        if(TextBox1.InvokeRequired)
        {
            ChangeTextBoxDelegate ct = SetTextBox1Text;
            TextBox1.BeginInvoke(ct,text);
        }
        else
        {
            TextBox1.Text = text;
        }
    }
    
    private void myJob(object obj)
    {
            SetTextBox1Text((double)obj * Math.PI).ToString());
    }
    參考:http://www.cnblogs.com/yizhu2000/archive/2007/10/12/922637.html
    html

相關文章
相關標籤/搜索