天天看點

同步,異步,多線程,你怎麼看?

  講解同步與異步的文章多如牛毛,個人的了解,簡單地說同步就是串行,異步就是并行。同步的情況下,A調用B,A等B執行完成後接着執行,自始至終隻有一個線程在運作;而異步時,A調用B,B執行,A也繼續執行,這個過程中有兩個線程在運作。本文通過winform下的一個執行個體講解同步與異步的差别,本文的例子很簡單,适合初學者。

  1.同步

  大家應該經常碰到這種情況,點選界面上某個按鈕或者某個控件後界面卡死的情況,個人覺得其中一個原因可能是主線程的問題,界面主線程在背景處理其他任務,沒法同時響應使用者的操作。看一個最簡單的例子,界面如下:

  

同步,異步,多線程,你怎麼看?

代碼:

private void btnCalc_Click(object sender, EventArgs e)        

{            

   int sum = Calc(100);            

  rtxtMain.Text = "calc over, result is " + sum;            

  MessageBox.Show("計算完成", "提示");        

}

        private int Calc(int n)        

  int sum = 0;            

  Thread.Sleep(TimeSpan.FromSeconds(20));            

  for (int i = 0; i < n; i++)            

  {                

    sum += i;            

  }            

  return sum;        

  很明顯,使用這種方法時點選按鈕後界面就卡住,直到背景方法執行完才響應。原因是隻有主線程在運作,那麼咱們再重新起一個新線程,可以自己另起一個線程,或者使用.NET提供的異步方法。

  2.異步

  .NET異步時重新從線程池中啟動了一個線程,本例中這個線程負責執行背景的方法,界面主線程繼續響應使用者的操作。線程池線程執行完背景方法後彈出提示框提示主線程工作已做完。代碼如下:

  public delegate int CalcEventHandler(int n);     //定義委托

    public partial class MainFrm : Form    

  {        

    public MainFrm()        

     {            

      InitializeComponent();            

      Control.CheckForIllegalCrossThreadCalls = false;          //禁用非法跨線程調用檢查

    }

          private void btnCalc_Click(object sender, EventArgs e)        

    {            

      CalcEventHandler mycalc = new CalcEventHandler(Calc);            

      AsyncCallback async = new AsyncCallback(OnComplete);             //回調方法

      mycalc.BeginInvoke(100, async, "this is your data" );                  //執行異步

      int sum = 0;            

      Thread.Sleep(TimeSpan.FromSeconds(20));            

      for (int i = 0; i < n; i++)            

      {                

        sum += i;            

      }            

      return sum;        

   //異步完成後執行的回調方法

        private void OnComplete(IAsyncResult asycResult)        

   {            

    AsyncResult result = (AsyncResult)asycResult;            

    CalcEventHandler del = (CalcEventHandler)result.AsyncDelegate;      //向下轉換      

    int sum = del.EndInvoke(asycResult);     //擷取傳回值           

    string data = result.AsyncState != null ? result.AsyncState.ToString() : string.Empty;           //擷取傳遞的資料

     rtxtMain.Text = "calc over, 結果為 " + sum + ", 傳遞資訊為 " + data;            

    MessageBox.Show("計算完成","提示");         //提示主線程

  }    

結果如下:

同步,異步,多線程,你怎麼看?

  這樣,界面不會出現卡死的情況,可以提高使用者體驗。當然這隻是一個簡單的例子。

  還有一種方法就是,自己另外啟一個線程,代碼如下:

  private void btnCalc_Click(object sender, EventArgs e)        

  {              

    Thread tr = new Thread(new ThreadStart(Calc));       //啟動新線程      

    tr.Start();        

  }

        private void Calc()      //重載方法   

  {            

    Calc(100);        

  private int Calc(int n)        

    int sum = 0;            

    Thread.Sleep(TimeSpan.FromSeconds(5));            

    for (int i = 0; i < n; i++)            

    {                

      sum += i;            

    }            

    rtxtMain.Text = "calc over, 結果為 " + sum;             //提示移到這裡

    MessageBox.Show("計算完成", "提示");           

    return sum;        

小結:

  1.這個例子很簡單,用于了解同步和異步的差別和作用。

   2.同步和異步跟為委托和多線程是相關聯的,有興趣的朋友繼續學習委托和多線程相關知識。

本文寫的很簡單,謝謝你的閱讀,如果有好的建議或方法,歡迎留言,一起交流~~