多线程总结之旅(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对象,该对象包含有关当前线程的各类上下文的信息

相关文章
相关标签/搜索