C#線程處理

  C#支持經過多線程並行地執行代碼,一個線程有它獨立的執行路徑,可以與其它的線程同時地運行。一個C#程序開始於一個單線程,這個單線程是被CLR和操做系統(也稱爲「主線程」)自動建立的,並具備多線程建立額外的線程。
  除非被指定,不然全部的例子都假定如下命名空間被引用了:git

using System;
using System.Threading;

C#開啓線程的方法有:github

  • 異步委託
  • 經過Thread類
  • 線程池
  • 任務

  總的來講其實線程的開啓基本都涉及到委託的使用。c#

1、異步委託開啓線程

首先來看一個比較簡單的例子,採用第一種開啓線程的方法——異步委託多線程

using System;
using System.Threading;

namespace Study
{
    class Program
    {
        static void test()
        {
            Console.WriteLine("TestThread");
        }
        static void Main(string[] args)
        {
            Action a = test;
            a.BeginInvoke(null, null);
            Console.WriteLine("MainThread");
            Console.ReadLine();
        }
    }
}

  編譯運行,發現結果與預期有所不一樣。結果以下圖
Thread
  若是按着逐行運行代碼的方式,那麼應該是先輸出TestThread,可是結果倒是先輸出MainThread。
  將a.BeginInvoke(null,null);Console.WriteLine("MainThread");對調位置以後,結果和以前的依然一致。這就說明,異步委託開啓的線程是和主線程同時同步進行的。
  Action委託是指向一個沒有返回值的函數,那麼假設一個線程,咱們須要取得他的返回結果並輸出,那麼就要用到Func委託。
  看下面的源碼異步

using System;
using System.Threading;

namespace SummerStudy
{
    class Program
    {
        static string test(int i, string str)
        {
            Console.WriteLine("TestThread" + "\t參數i是:" + i);
            return str;
        }
        static void Main(string[] args)
        {
            Func<int, string, string> a = test;
            IAsyncResult res = a.BeginInvoke(1, "返回值", null, null);
            string o = a.EndInvoke(res);
            Console.WriteLine("MainThread\t" + "線程返回值是:" + o);
            Console.ReadLine();
        }
}

Thread
同時異步委託開啓線程中,判斷線程是否結束的方法也有兩種,一種是利用IAsyncResult的IsCompleted方法,一種是使用方法進行線程結束判斷。
  具體使用方法以下。函數

  1. IsCompleted(bool)
IAsyncResult ia = a.BeginInvoke()
if(ia.IsCompleted == false)
{
    //GoOn
}
  1. AsyncWaitHandle
IAsyncResult ia = a.BeginInvoke()
ia.AsyncWaitHandle.WaitOne(Time);//Time爲等待時間,超時後纔會運行下一行代碼,未完成直接跳出返回false

  或者經過自定義方法,BeginInvoke中倒數第二個參數是一個委託,傳遞一個函數,在線程結束以後會自動的調用。spa

static string Test(int a)
{

}
Func<int, string> a = Test;
IAsyncResult ia = a.BeginInvoke(100, CallBack, a);
static void CallBack(IAsyncResult ar)
{
    Func<int, string> a = ia.AsyncState as Func<int, string>;
    string res = a.EndInvoke(ar);
}

  在使用Lambda表達式做爲委託的時候,最後一個參數能夠爲空,由於Lambda表達式能夠訪問外部變量。操作系統

2、使用Thread類開啓線程

  使用Thread類建立一個實例,它的構造方法中須要傳遞一個委託。經過委託綁定線程。
  直接上代碼線程

using System;
using System.Threading;

namespace Study
{
    class Program
    {
        static void test()
        {
            Console.WriteLine("Thread");
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");
        }
        static void Main(string[] args)
        {
            Thread t = new Thread(test);
            t.Start();
            Console.WriteLine("Main");
            Console.Read();
        }
    }
}

Thread
  對於須要傳遞參數的委託,則必須制定參數類型爲object,在線程Start方法中傳遞參數code

namespace SummerStudy
{
    class Program
    {
        static void test(object c)
        {
            int id = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Thread,\t線程id爲" + id + ",\t參數是:" + c);
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");

        }
        static void Main(string[] args)
        {
            Thread t = new Thread(test);
            t.Start("xxx.avi");
            Console.WriteLine("Main");
            Console.Read();
        }
    }
}

Thread
  固然你也能夠自定義一個類,在類中自定義數據傳遞。

3、線程池

  這種方法有助於節省時間,具體使用方法以下

using System;
using System.Threading;

namespace SummerStudy
{
    class Program
    {
        static void test(object c)
        {
            int id = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Thread,\t線程id爲" + id + ",\t參數是:" + c);
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");

        }
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(test, "asfasf");
            Console.Read();
        }
    }
}

  其中委託必需要有一個參數,不管是否使用該參數。且只適用於使用時間短的線程,不能改變優先級

4、任務

  使用Task類開啓線程,還有TaskFactory建立
  Task類實例

using System;
using System.Threading;
using System.Threading.Tasks;

namespace SummerStudy
{
    class Program
    {
        static void test(object c)
        {
            int id = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Thread,\t線程id爲" + id);
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");

        }
        static void Main(string[] args)
        {
            Task t = new Task(test, "Asfgasg");
            t.Start();

            //或者

            TaskFactory tf = new TaskFactory();

            Task t1 = tf.StartNew(test);
            Console.Read();
        }
    }
}

個人掘金:WarrenRyan

個人簡書:WarrenRyan

歡迎關注個人博客得到第一時間更新 https://blog.tity.xyz

個人Github:WarrenRyan

個人博客園:WarrenRyan

相關文章
相關標籤/搜索