1.创建线程
using System;
using System.Threading;
namespace Threading {
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello World!");
Thread t = new Thread(PrintNumbers);
t.Start();
PrintNumbers();
Console.ReadLine();
}
static void PrintNumbers() {
Console.WriteLine("Starting...");
for (int i = 0; i < 10; i++) {
Console.WriteLine(i);
}
}
}
}
2.线程休眠
3.线程等待
Thread.Join();等待线程处于阻塞状态,工作线程执行完,主线程开始,工作线程执行期间主线程处于阻塞状态。
using System;
using System.Threading;
namespace Threading {
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello World!");
Thread t = new Thread(PrintNumbers);
t.Start();
t.Join();
PrintNumbers();
Console.ReadLine();
}
static void PrintNumbers() {
Console.WriteLine("Starting...");
for (int i = 0; i < 10; i++) {
// Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
}
}
4.检测线程状态
CurrentThread.ThreadState.ToString()
using System;
using System.Threading;
namespace Threading {
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello World!");
Thread t = new Thread(PrintNumbers);
t.Start();
Console.WriteLine(t.ThreadState.ToString());
t.Join();
Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
PrintNumbers();
Console.ReadLine();
}
static void PrintNumbers() {
Console.WriteLine("Starting...");
for (int i = 0; i < 10; i++) {
// Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
Console.WriteLine(i);
}
}
}
}
5.线程优先级
执行第一个RunThreads(),几乎同一时间执行,设置单核运行后,计算耗时将超过2s,CPU核心大部分时间在运行高优先级线程,只留给剩下的线程很少的时间来运行。 Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1)
using System;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
namespace Threading {
class Program {
static void Main(string[] args) {
Console.WriteLine($"Current thread priority:{Thread.CurrentThread.Priority}");
Console.WriteLine($"RUnning on all cores available");
RunThreads();
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("Running on a single core");
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);//设置当前的进程的单核运行
//表示关联进程内的线程可以在其上运行的处理器。 默认值取决于计算机上的处理器数。 默认值为 2 n - 1,其中 n 是处理器数。
RunThreads();
Console.ReadLine();
}
static void RunThreads() {
var sample = new ThreadSample();
var threadOne = new Thread(sample.CountNumbers);
threadOne.Name = "ThreadOne";
var threadTwo = new Thread(sample.CountNumbers);
threadTwo.Name = "ThreadTwo";
threadOne.Priority = ThreadPriority.Highest;
threadTwo.Priority = ThreadPriority.Lowest;
threadOne.Start();
threadTwo.Start();
Thread.Sleep(TimeSpan.FromSeconds(2));
sample.Stop();
}
}
public class ThreadSample {
private bool _isStopped = false;
public void Stop() {
_isStopped = true;
}
public void CountNumbers() {
long counter = 0;
while (!_isStopped) {
counter++;
}
Console.WriteLine($"{Thread.CurrentThread.Name} with" + $"{Thread.CurrentThread.Priority,11}");
}
}
}
6.前台线程和后台线程
设置线程二为后台线程,但前台线程结束后,后台线程立刻被终止。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
namespace Threading {
class Program {
static void Main(string[] args) {
var sampleForegroud = new ThreadSample(10);
var sampleBackgroud = new ThreadSample(20);
var threadOne = new Thread(sampleForegroud.CountNumbers);
threadOne.Name = "ForegroudThread";
var threadTwo = new Thread(sampleBackgroud.CountNumbers);
threadTwo.Name = "BackgroudThread";
threadTwo.IsBackground = true;//设置线程二为后台线程,但前台线程结束后,后台线程立刻被终止。
threadOne.Start();
threadTwo.Start();
}
}
class ThreadSample {
private readonly int _iterations;
public ThreadSample(int iterations) {
_iterations = iterations;
}
public void CountNumbers() {
for (int i = 0; i < _iterations; i++) {
Thread.Sleep(1);
Console.WriteLine($"{Thread.CurrentThread.Name}print {i}");
}
}
}
}
7.向线程传递参数
Thread.Start() 两个重载方法,可传递参数进入线程调用的函数中。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
namespace Threading {
class Program {
static void Main(string[] args) {
var sample = new ThreadSample(10);
var threadOne = new Thread(sample.CountNumbers);
threadOne.Start();
threadOne.Join();//Join 一个同步方法,该方法阻止调用线程 (即,调用方法的线程) ,直到 Join 调用方法的线程完成。
//使用此方法可以确保线程已终止。 如果线程未终止,调用方将无限期阻止。
Console.WriteLine("==========我是分割线=================");
var threadTwo = new Thread(Count);
threadTwo.Name = "ThreadTwo";
threadTwo.Start(8);
threadTwo.Join();
Console.WriteLine("==========我是分割线=================");
var threadThree = new Thread(() => CountNumbers(12));
threadThree.Name = "ThreadThree";
threadThree.Start();
}
static void Count(object iterations) {
CountNumbers((int)iterations);
}
static void CountNumbers(int iterations) {
for (int i = 0; i < iterations; i++) {
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
}
}
static void PrintNumber(int number) {
Console.WriteLine(number);
}
}
class ThreadSample {
private readonly int _iterations;
public ThreadSample(int iterations) {
_iterations = iterations;
}
public void CountNumbers() {
for (int i = 0; i < _iterations; i++) {
Thread.Sleep(1);
Console.WriteLine($"{Thread.CurrentThread.Name}print {i}");
}
}
}
}
8.使用死锁lock
8.1 为什么要lock,lock了什么?
当我们使用线程的时候,效率最高的方式当然是异步,即各个线程同时运行,其间不相互依赖和等待。但当不同的线程都需要访问某个资源的时候,就需要同步机制了,也就是说当对同一个资源进行读写的时候,我们要使该资源在同一时刻只能被一个线程操作,以确保每个操作都是有效即时的,也即保证其操作的原子性。lock是C#中最常用的同步方式,格式为lock(objectA){codeB} 。
lock(objectA){codeB} 看似简单,实际上有三个意思,这对于适当地使用它至关重要:
1. objectA被lock了吗?没有则由我来lock,否则一直等待,直至objectA被释放。
2. lock以后在执行codeB的期间其他线程不能调用codeB,也不能使用objectA。
3. 执行完codeB之后释放objectA,并且codeB可以被其他线程访问。
8.2 lock演示
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Lock {
class Program {
static void Main(string[] args) {
var c = new Counter(); //多态
Thread threadOne = new Thread(()=>TestCount(c));
Thread threadTwo = new Thread(() => TestCount(c));
Thread threadThree = new Thread(() => TestCount(c));
threadOne.Start();
threadTwo.Start();
threadThree.Start();
threadOne.Join();
threadTwo.Join();
threadThree.Join();
Console.WriteLine($"{c.Count}");
Console.WriteLine($"This is lock example");
var cL = new CounterWithLock();
Thread threadFour = new Thread(() => TestCount(cL));
Thread threadFive = new Thread(() => TestCount(cL));
threadFour.Start();
threadFive.Start();
Console.WriteLine($"{cL.Count}");
Console.ReadLine();
}
static void TestCount(CounterBase c) {
for (int i = 0; i < 1000; i++) {
c.Increment();
c.Decrement();
}
}
}
abstract class CounterBase {
public abstract void Increment();
public abstract void Decrement();
}
class Counter : CounterBase {
public int Count { get; private set; }
public override void Decrement() {
Count--;
}
public override void Increment() {
Count++;
}
}
class CounterWithLock : CounterBase {
public int Count { get; private set; }
private readonly object _syncRoot = new object();
public override void Increment() {
lock (_syncRoot) {//可能会造成性能问题,死锁。
Count++;
}
}
public override void Decrement() {
lock (_syncRoot) {
Count--;
}
}
}
}
8.3 lock死锁演示

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Monitor {
class Program {
static void Main(string[] args) {
var lock1 = new object();
var lock2 = new object();
new Thread(() => LockTooMuch(lock1, lock2)).Start();
lock (lock2) {
Console.WriteLine("lock2 Main");
lock (lock1) {
Console.WriteLine("lock1 Main");
}
}
Console.ReadLine();
}
static void LockTooMuch(object lock1,object lock2) {
lock (lock1) {
Thread.Sleep(3000);
lock (lock2) {
Console.WriteLine("lock2 Thread");
}
}
}
}
}
9.使用Monitor类避免死锁
TryEnter()尝试进入,进不去则返回False
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MonitorExample {
class Program {
static void Main(string[] args) {
var lock1 = new object();
var lock2 = new object();
new Thread(() => LockTooMuch(lock1, lock2)).Start();
lock (lock2) {
Console.WriteLine("lock2 Main");
if (Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5000))) {
Console.WriteLine("Access Successfully");
}
else {
Console.WriteLine("Access Unsuccessfully");
}
}
Console.ReadLine();
}
static void LockTooMuch(object lock1,object lock2) {
lock (lock1) {
Thread.Sleep(3000);
lock (lock2) {
Console.WriteLine("lock2 Thread");
}
}
}
}
}
10.TryCatch
.NETFramework(1.0/1.1)未被捕获的异常不会强制应用程序关闭。可以通过添加一个包含以下代码片段的应用程序配置文件(app.config)来使用该策略。
<configuration>
<runtime>
<legacyUnhandleExceptionPolicy enable="1"/>
</runtime>
</configuration>