多線程總結之旅(4):多線程的建立、屬性

能夠參考微軟文檔:https://msdn.microsoft.com/en-us/library/system.threading.thread(v=vs.110).aspx數組

 

 

1、Thread  安全

  一、多線程執行無參數的方法:多線程

  (1)線程用Thread類來建立, 經過ThreadStart委託來指明方法從哪裏開始運行,調用Start方法後,線程開始運行,線程一直到它所調用的方法返回後結束。工具

 class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(new ThreadStart(Go));
            t.Start();
        }
        public static void Go()
        {
            Console.WriteLine("GO");           
        }
    }

  (2)固然也能夠不須要ThreadStart委託更便利地建立出來:在這種狀況,ThreadStart被編譯器自動推斷出來。測試

static void Main(string[] args)
        {
           Thread t = new Thread(Go);
            t.Start();
        }
        public static void Go()
        {
            Console.WriteLine("GO");           
        }

  (3)另外一個快捷的方式是使用匿名方法來啓動線程:this

 static void Main(string[] args)
        {
            Thread t = new Thread(delegate() {Console.WriteLine("GO");   });
            t.Start();
        }

  二、多線程執行有參數的方法  spa

  (1)有時候咱們須要給Go方法傳參來完成整個任務,但咱們不能使用ThreadStart委託,由於它不接受參數,所幸的是,.NET framework定義了另外一個版本的委託叫作ParameterizedThreadStart, 它能夠接收一個單獨的object類型參數:操作系統

class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(Go);
            t.Start(true);
        }
        public static void Go(object j)
        {
            Console.WriteLine("GO");           
        }
    }

  (2)ParameterizedThreadStart的特性是在使用以前咱們必需對咱們想要的類型(這裏是bool)進行裝箱操做,而且它只能接收一個參數。線程

  一個替代方案是使用一個匿名方法調用一個普通的方法以下:調試

 static void Main(string[] args)
        {
            Thread t = new Thread(delegate() { Go("jack", "hello"); });
           t.Start();
            Console.ReadKey();
        }
        public static void Go(string name,string saying)
        {
            Console.WriteLine("{0},{1}",name,saying);           
        }

  (3)優勢是目標方法(這裏是Go),能夠接收任意數量的參數,而且沒有裝箱操做。不過這須要將一個外部變量放入到匿名方法中,匿名方法打開了一種怪異的現象,當外部變量被後來的部分修改了值的時候,可能會透過外部變量進行無心的互動。有意的互動(一般經過字段)被認爲是足夠了!一旦線程開始運行了,外部變量最好被處理成只讀的——除非有人願意使用適當的鎖。

static void Main(string[] args)
        {
            string test = "Tom";
            Thread t = new Thread(delegate() { Go(test, "hello"); });
           test = "Jack";
            t.Start();
            Console.ReadKey();
        }
        public static void Go(string name,string saying)
        {
            Console.WriteLine("{0},{1}",name,saying);           
        }

  (4)另外一種較常見的方式是將對象實例的方法而不是靜態方法傳入到線程中,對象實例的屬性能夠告訴線程要作什麼

class Program
    {
        bool lower = false;
        static void Main(string[] args)
        {
            Program test = new Program();
            test.lower = true;
            Thread t = new Thread(test.Go);          
            t.Start();
            Console.ReadKey();
        }
        void Go()
        {
            Console.WriteLine(lower?"Hello":"hello");           
        }
    }

2、Thread的屬性

  一、靜態屬性和動態屬性。靜態屬性包括CurrentThread ,CurrentContext,CurrentPrincipal(負責人);動態屬性包括Priority,ThreadState ,IsAlive,IsBackground,IsThreadPoolThread,ManagedThreadId,ApartmentState,CurrentCulture,CurrentUICulture,ExecutionContext,Name

  (1)CurrentThread 和Name的使用

    線程能夠經過它的Name屬性進行命名,這很是有利於調試:能夠用Console.WriteLine打印出線程的名字,Microsoft Visual Studio能夠將線程的名字顯示在調試工具欄的位置上。線程的名字能夠在被任什麼時候間設置——但只能設置一次,重命名會引起異常。

    CurrentThread  獲取正在運行的線程。 

static void Main(string[] args)
        {
          
            Thread t = new Thread(Go);
            t.Name = "我是子線程";
            t.Start();
            Console.ReadKey();
        }
        static void Go()
        {
            string currentThread = Thread.CurrentThread.Name;
            Console.WriteLine(currentThread);           
        }

  (2)CurrentContext:獲取正在執行線程的當前上下文(線程上下文是指:線程運行須要的環境,參數等條件)

 static void Main(string[] args)
        {
          
            Thread t1 = new Thread(Go);           
            t1.Start();                 
            Console.ReadKey();
            
        }
        static void Go()
        {            
            //獲取當前上下文的上下文ID
            int currentContextId = Thread.CurrentContext.ContextID;
            Console.WriteLine(currentContextId);           
        }

  (3)CurrentPrincipal 獲取或設置線程的當前負責人(對基於角色的安全性而言)

 

 static void Main(string[] args)
        {
          string[] rolesArray = {"managers", "executives"};
            try
            {
                // 設置當前負責人。從用戶表示和角色名稱數組初始化
                Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), rolesArray);
            }
            catch(SecurityException secureException)
            {
                Console.WriteLine("{0}: Permission to set Principal " +
                    "is denied.", secureException.GetType().Name);
            }

            IPrincipal threadPrincipal = Thread.CurrentPrincipal;
            Console.WriteLine("Name: {0}\n是否定證: {1}" +"\n認證的類別: {2}", 
                threadPrincipal.Identity.Name, 
                threadPrincipal.Identity.IsAuthenticated,
                threadPrincipal.Identity.AuthenticationType);
            Console.ReadKey() ;
        }

  (4)IsAlive  獲取一個值,該值指示當前線程的執行狀態。經測試只有 Unstarted、Stopped 返回false;其餘線程狀態都返回true。它的定義以下:只讀

  public bool IsAlive { get; }

  (5)IsBackground 獲取或設置一個值,該值指示某個線程是否爲後臺線程。它的定義以下:能夠讀寫操做。    

public bool IsBackground {
    get;
    [HostProtectionAttribute(SecurityAction.LinkDemand, SelfAffectingThreading = true)]
    set;
}

    線程默認爲前臺線程,這意味着任何前臺線程在運行都會保持程序存活。C#也支持後臺線程,當全部前臺線程結束後,它們不維持程序的存活。 改變線程從前臺到後臺不會以任何方式改變它在CPU協調程序中的優先級和狀態。線程的IsBackground屬性控制它的先後臺狀態,以下實例:

 

class PriorityTest {
  static void Main (string[] args) {
    Thread worker = new Thread (delegate() { Console.ReadLine(); });
    if (args.Length > 0) worker.IsBackground = true;
    worker.Start();
  }
}

  (6)Priority 獲取或設置一個值,該值指示線程的調度優先級。

    優先級別有如下五種:Highest、AboveNormal、Normal、BelowNormal、Lowest。默認爲Normal.只有多個線程同時爲活動時,優先級纔有做用。  設置一個線程的優先級爲高一些,並不意味着它能執行實時的工做,由於它受限於程序的進程的級別。要執行實時的工做,必須提高在System.Diagnostics 命名空間下Process的級別,像下面這樣:Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;

 

     ProcessPriorityClass.High 實際上是一個短暫缺口的過程當中的最高優先級別:Realtime。設置進程級別到Realtime通知操做系統:你不想讓你的進程被搶佔了。若是你的程序進入一個偶然的死循環,能夠預期,操做系統被鎖住了,除了關機沒有什麼能夠拯救你了!基於此,High大致上被認爲最高的有用進程級別。

  

  (7)IsThreadPoolThread  獲取一個值,該值指示線程是否屬於託管線程池

 

using System;
using System.Threading;

class IsThreadPool
{
    static void Main()
    {
        AutoResetEvent autoEvent = new AutoResetEvent(false);

        Thread regularThread = new Thread(new ThreadStart(ThreadMethod));
        regularThread.Start();
        ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod),autoEvent);

        // Wait for foreground thread to end.
        regularThread.Join();

        // Wait for background thread to end.
        autoEvent.WaitOne();
        Console.ReadKey();
    }

    static void ThreadMethod()
    {
        Console.WriteLine("ThreadOne, executing ThreadMethod, " + "is {0}from the thread pool.",Thread.CurrentThread.IsThreadPoolThread ? "" : "not ");
    }

    static void WorkMethod(object stateInfo)
    {
        Console.WriteLine("ThreadTwo, executing WorkMethod, " + "is {0}from the thread pool.",Thread.CurrentThread.IsThreadPoolThread ? "" : "not ");

        // Signal that this thread is finished.
        ((AutoResetEvent)stateInfo).Set();
    }
}

  (8)ManagedThreadId 獲取當前託管線程的唯一標識符:它的定義以下:只讀

public int ManagedThreadId { get; }

 

  (9)ApartmentState 獲取或設置此線程的單元狀態

using System;
using System.Threading;

class ApartmentTest
{
    static void Main()
    {
        Thread newThread =new Thread(new ThreadStart(ThreadMethod));
        newThread.SetApartmentState(ApartmentState.MTA);
        Console.WriteLine("ThreadState: {0}, ApartmentState: {1}",newThread.ThreadState, newThread.ApartmentState);
        newThread.Start();

        // Wait for newThread to start and go to sleep.
        Thread.Sleep(300);
        try
        {
            // This causes an exception since newThread is sleeping.
            newThread.SetApartmentState(ApartmentState.STA);
        }
        catch (ThreadStateException stateException)
        {
            Console.WriteLine("\n{0} caught:\n" +"Thread is not in the Unstarted or Running state.",stateException.GetType().Name);
            Console.WriteLine("ThreadState: {0}, ApartmentState: {1}",newThread.ThreadState, newThread.GetApartmentState());
        }
        Console.ReadKey();
    }

    static void ThreadMethod()
    {
        Thread.Sleep(1000);
    }
}

 

  (10)CurrentCulture 獲取或設置當前線程的區域性

using System;
using System.Threading;
using System.Windows.Forms;

class UICulture : Form
{
    public UICulture()
    {
        // Set the user interface to display in the
        // same culture as that set in Control Panel.
        Thread.CurrentThread.CurrentUICulture =Thread.CurrentThread.CurrentCulture;

        // Add additional code.
    }

    static void Main()
    {
        Application.Run(new UICulture());
    }
}

 

  (11)CurrentUICulture 獲取或設置資源管理器使用的當前區域性以便在運行時查找區域性特定的資源

using System;
using System.Globalization;
using System.Threading;

public class Example
{
    public static void Main()
    {
        // Change the current culture if the language is not French.
        CultureInfo current = Thread.CurrentThread.CurrentUICulture;
        if (current.TwoLetterISOLanguageName != "fr")
        {
            CultureInfo newCulture = CultureInfo.CreateSpecificCulture("en-US");
            Thread.CurrentThread.CurrentUICulture = newCulture;
            // Make current UI culture consistent with current culture.
            Thread.CurrentThread.CurrentCulture = newCulture;
        }
        Console.WriteLine("The current UI culture is {0} [{1}]",
                          Thread.CurrentThread.CurrentUICulture.NativeName,
                          Thread.CurrentThread.CurrentUICulture.Name);
        Console.WriteLine("The current culture is {0} [{1}]",
                          Thread.CurrentThread.CurrentUICulture.NativeName,
                          Thread.CurrentThread.CurrentUICulture.Name);
        Console.ReadKey();
    }
}

 

  (12)ExecutionContext 獲取一個Executioncontext對象,該對象包含有關當前線程的各類上下文的信息

相關文章
相關標籤/搜索