WPF-17 多线程

线程定义:线程是操作系统能够运行调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并行多个线程,每条线程并行执行不同的任务.在.NET 中 Thread 在System.Threading 命名空间下,该命名空间所属System.Threading.Thread.dll继承结构:Object->CriticalFinalizerObject->Thread

1.创建一个线程

我们先来看一下线程构造函数,总共4个构造函数,我们主要讲解红色框内的构造,另外两个是对应的重载..

WPF-17 多线程

ThreadStart 委托,该委托没有参数,定义如下:

public delegate void ThreadStart();

下面代码创建和启动一个线程执行ExecuteInForeground方法.这些方法打印一些线程属性,该线程从开始到循环结束至少执行5S.

using System;using System.Diagnostics;using System.Threading;public class Example{   public static void Main()   {      var th = new Thread(ExecuteInForeground);      th.Start();      Thread.Sleep(1000);      Console.WriteLine("Main thread ({0}) exiting...",                        Thread.CurrentThread.ManagedThreadId);   }   private static void ExecuteInForeground()   {      var sw = Stopwatch.StartNew();      Console.WriteLine("Thread {0}: {1}, Priority {2}",                        Thread.CurrentThread.ManagedThreadId,                        Thread.CurrentThread.ThreadState,                        Thread.CurrentThread.Priority);      do {         Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",                           Thread.CurrentThread.ManagedThreadId,                           sw.ElapsedMilliseconds / 1000.0);         Thread.Sleep(500);      } while (sw.ElapsedMilliseconds <= 5000);      sw.Stop();   }}

输出结果:

WPF-17 多线程

从输出结果可以看出应用程序主线程退,但是ExecuteInForeground仍然在运行,为什么主线程结束了ExecuteInForeground仍然在运行呢? 在文章结尾我们会进行说明。

ParameterizedThreadStart委托,该委托带有object 参数,定义如下:
public delegate void ParameterizedThreadStart(object obj);

下面例子定义了一个有参委托,并将参数通过Thread的Start方法传进去。

using System;using System.Diagnostics;using System.Threading;public class Example{   public static void Main()   {      var th = new Thread(ExecuteInForeground);      th.Start(4500);      Thread.Sleep(1000);      Console.WriteLine("Main thread ({0}) exiting...",                        Thread.CurrentThread.ManagedThreadId);   }   private static void ExecuteInForeground(Object obj)   {      int interval;      try {         interval = (int) obj;         Console.WriteLine("obj=" + interval);      }      catch (InvalidCastException) {         interval = 5000;      }      var sw = Stopwatch.StartNew();      Console.WriteLine("Thread {0}: {1}, Priority {2}",                        Thread.CurrentThread.ManagedThreadId,                        Thread.CurrentThread.ThreadState,                        Thread.CurrentThread.Priority);      do {         Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",                           Thread.CurrentThread.ManagedThreadId,                           sw.ElapsedMilliseconds / 1000.0);         Thread.Sleep(500);      } while (sw.ElapsedMilliseconds <= interval);      sw.Stop();   }}

输出结果如下:

WPF-17 多线程

一旦启动线程,就没有必要保留对 Thread 对象的引用。线程继续执行,直到线程过程完成

2. 线程属性

你能使用Thread静态属性CurrentThread获取当前运行线程实例.下面列举出线程一些常用属性:
属性 备注
ManagedThreadId 当前线程ID
Name 当前线程名称
ThreadState 当前线程的状态
IsBackground 当前线程是否是一个后端线程
Priority 当前线程优先级
IsThreadPoolThread 当前线程是否是一个线程池线程
CurrentCulture 当前线程语言文化
CurrentUICulture 当前线程UI的语言文化

下面例子打印线程常用一些属性:

using System;using System.Threading;public class Example{   static Object obj = new Object();      public static void Main()   {      ThreadPool.QueueUserWorkItem(ShowThreadInformation);      var th1 = new Thread(ShowThreadInformation);      th1.Start();      var th2 = new Thread(ShowThreadInformation);      th2.IsBackground = true;      th2.Start();      Thread.Sleep(500);      ShowThreadInformation(null);    }   private static void ShowThreadInformation(Object state)   {        lock (obj)        {            var th = Thread.CurrentThread;            Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId);            Console.WriteLine("   Thread Name:{0}",th.Name);            Console.WriteLine("   Thread ThreadState:{0}", th.ThreadState);            Console.WriteLine("   Background thread: {0}", th.IsBackground);            Console.WriteLine("   Thread pool thread: {0}", th.IsThreadPoolThread);            Console.WriteLine("   Priority: {0}", th.Priority);            Console.WriteLine("   Culture: {0}", th.CurrentCulture.Name);            Console.WriteLine("   UI culture: {0}", th.CurrentUICulture.Name);            Console.WriteLine();        }    }}

输出结果如下:

WPF-17 多线程

3.前段线程(foreground thread)和后端线程(background thread)

可以通过设置Thread 属性IsBackground将当前线程设置为前段线程或者后端线程.前段线程和后台线程唯一的区别是:如果所有的前段线程都停止,如果后端线程运行中也会跟着停止,所有的前段线程都停止,运行时会关闭所有的后端线程。

默认情况下,通过下面两种方式创建的线程为前段线程:

  • 应用程序主线程。

  • 通过调用thread类构造函数创建的线程。

默认情况下,通过下面两种方式创建的线程为后端线程:
  • 通过ThreadPool 线程池创建的线程.

  • 从非托管代码进入托管执行环境的所有线程

可以通过设置IsBackground 属性将一个线程设置为后端线程.只要应用程序运行,后端线程就一直运行,但是它不会阻止应用程序终止.例如:监视文件系统变化或传入的套接字连接。
我们引用文章开始的第一个例子,唯一区别就是将ExecuteInForeground设置成后端线程.
using System;using System.Diagnostics;using System.Threading;public class Example{   public static void Main()   {      var th = new Thread(ExecuteInForeground);      th.IsBackground = true;      th.Start();      Thread.Sleep(1000);      Console.WriteLine("Main thread ({0}) exiting...",                        Thread.CurrentThread.ManagedThreadId);   }   private static void ExecuteInForeground()   {      var sw = Stopwatch.StartNew();      Console.WriteLine("Thread {0}: {1}, Priority {2}",                        Thread.CurrentThread.ManagedThreadId,                        Thread.CurrentThread.ThreadState,                        Thread.CurrentThread.Priority);      do {         Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds",                           Thread.CurrentThread.ManagedThreadId,                           sw.ElapsedMilliseconds / 1000.0);         Thread.Sleep(500);      } while (sw.ElapsedMilliseconds <= 5000);      sw.Stop();   }}

输出结果如下,从输出结果我们可以看出应用程序主线程终止,ExecuteInForeground不会继续运行也会跟着退出

WPF-17 多线程

总结:

1.ParameterizedThreadStart ThreadStart委托可以创建一个线程。

2.线程相关联属性。

3.前段线程和后端线程的区别,如果想等待后端线程结束后再停止应用程序,需要使用特殊对象来实现线程通信。