1.2 ~ 1.8 线程:创建、暂定、等待、终止、状态、优先级、前台线程和后台线程

1.2 使用C#创建线程

  • 结果两组范围是1到10的数字会随机交叉输出。说明PrintNumber方法同时运行在主线程和另一个线程中。
  • 在运行的程序是一个进程,一个进程是n个线程,始终有1个线程作为主线程。
  • Thread t = new Thread(支持ParameterizedThreadStart和ThreadStart委托); ,ParameterizedThreadStart用t.Start(参数)执行(本方法只能传一个参数,如果想传多个参数,可以传集合),后者用t.Start()方法执行。
static void Main(string[] args)
{
	#region
	Thread t = new Thread(Class1_1.PrintNumbers);
	t.Start();
	Class1_1.PrintNumbers();
	Console.ReadLine();
	#endregion
}
public class Class1_1
{
	public static void PrintNumbers()
	{
		Console.WriteLine("staring...");
		for (int i = 0; i < 10; i++)
		{
			Console.WriteLine(i);
		}
	}
}

1.3 暂定线程

  • 让一个线程等待一段时间而不耗费操作系统资源。Thread.Sleep(1000);,线程暂停1s。
static void Main(string[] args)
{
	Thread t = new Thread(printNumbrWithDelay);
	t.Start();
	PrintNumbers();
	Console.ReadLine();
}
public static void printNumbrWithDelay()
{
	Console.WriteLine("staring...");

	for (int i = 0; i < 10; i++)
	{
		Thread.Sleep(TimeSpan.FromSeconds(2));//等待2s,
		Console.WriteLine(i);
	}
}


public static void PrintNumbers()
{
	Console.WriteLine("staring...");
	for (int i = 0; i < 10; i++)
	{
		Console.WriteLine(i);
	}
}
  • 代码说明:因为t线程每次打印数字时会休眠2s(休眠期间,会占用尽可能少的CPU时间),PrintNumbers会先打印完。

1.4 线程等待

  • 演示用Join方法让程序等待另一个线程执行完成。然后在代码中使用该线程的计算结果,用Thread.Sleep行不通,因为并不知道执行计算要花的具体时间。
static void Main(string[] args)
{
  #region 1.4
	Thread t = new Thread(Class1_4.PrintNumber);
	t.Start();
	t.Join();
	Console.WriteLine("thread 结束");
	Console.ReadLine();
	#endregion
}
public class Class1_4
{
        public static void PrintNumber()
        {
            Console.WriteLine("开始。。。");
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(500);
                Console.WriteLine(i);
            }
        }
}
  • 工作原理:当程序运行时,启动了一个耗时长的线程打印数字,但是主程序中调用了t.Join方法,该方法让我们等待直到线程t完成。主程序才会继续运行。借助该技术可以实现两个线程间同步执行步骤。第一个线程会等待另一个线程完成后再继续执行,类似于第一线程调Thread.Sleep方法让其处于阻塞状态,而t.Join方法好处是不用知道具体花费多长时间。

1.5 终止线程 t.Abort();

static void Main(string[] args)
{

		#region 1.5
		Thread t = new Thread(Class1_4.PrintNumber);
		t.Start();
		Thread.Sleep(3000);
		t.Abort();
		Console.WriteLine("线程{0}被终止了",Thread.CurrentThread.ManagedThreadId);
		 
		Class1_4.PrintNumber();
		#endregion
}
  • 工作原理:代码等待3s后对线程调用了t.Abort()是给线程t注入ThreadAbortException方法,导致线程终结。该异常很危险,因为可以在任何时候发生并且彻底摧毁应用程序,但是也不一定总能终结线程,目标线程可以通过处理该异常并调用Thread.ResetAbort方法来拒绝被终止。不推荐用abort关闭线程,可优先用其他方法,如CancellationToken方法取消线程的执行。

1.6 检测线程状态

  • 获得线程状态信息是非常有用的,因为线程是独立运行的,所以状态在任何时候都可以被改变。
  • Thread.CurrentThread.ThreadState获得线程状态枚举值,具体枚举值可以F12进去看看。
  • 始终可以通过Thread.CurrentThread静态属性获得当前线程对象。
Thread t = new Thread(Class1_6.PrintNumber);
Console.WriteLine(t.ThreadState.ToString());

public static void PrintNumber()
{
	Console.WriteLine("开始。。。");
	Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
	for (int i = 0; i < 10; i++)
	{
		Thread.Sleep(2000);
		Console.WriteLine(i);
	}
}

1.7 线程优先级

  • 线程优先级决定了该线程可占用多少CPU时间。
  • t.Priority = ThreadPriority.Highest;//设置线程优先级(最高优先级),Lowest(最低优先级)。在多核CPU中实际可能二者运行感觉没啥区别或很接近(单核时区别才会明显),但是如果有其他程序占用所有CPU核心,结果则会截然不同。设置Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);选项来模拟该情形,让操作系统将所有线程运行在单个CPU核心(第一个核心)上,得到结果是优先级高的得到运算时间多于优先级低的线程。

1.8 前台线程和后台线程

var t2 = new Thread(本处省略无参方法名);
t2.IsBackground = true;//设置为后台线程,不设置则该线程默认为前台线程

  • 前台线程和后台线程区别:默认创建的线程是前台线程,设置IsBackGround为true则为后台线程,所有前台线程结束则程序结束,而此时后台线程还可以继续运行。

posted on 2019-10-28 08:09  anjun_xf  阅读(150)  评论(0编辑  收藏  举报

导航

TOP