欢迎光临
我们一直在努力

C#学习08 多线程

  • 一、多线程
    • 1、线程的基础概念
    • 2、线程的创建
    • 3、线程的运行
    • 3、线程的终止及休眠
    • 4、完整代码

一、多线程

1、线程的基础概念

  • (1)进程:进程是操作系统进行资源分配和管理的基本单位,可以看作是数据集合上的一次运行活动
  • (2)线程:线程是操作系统能进行运算调度的最小单位,线程包含在进程中,是进程实际运行单位

2、线程的创建

  • (1)线程类 Thread,需要引用命名空间 using System.Threading
  • (2)创建线程实列 Thread t = new Thread(传入一个委托)

(A)该线程要执行的内容要封装在传入的委托之中 (B)允许传入参数,这里Thread的参数类型的委托为ParameterizedThreadStart,而他的参数类型固定为 object, 因此实际传入的参数可以是任意类型

在这里插入图片描述

3、线程的运行

  • (1)线程的运行 Thread.start()

有参数则传入对应参数,反之不填

在这里插入图片描述 运行结果 在这里插入图片描述

  • (2)在多线程中,线程之间会共享数据

(A)在多线程中,线程会同时操作同一片内存空间,因此可能会导致数据串联的现象,如在下面的代码中,会出现以下问题

(a)问题:两个线程可能会同时取出队列中的同一元素 (b)问题:队列取空 在这里插入图片描述 左图结果为:两个线程同时取出队列中的同一元素c 右图结果为:线程thread1已经取出最后一个元素,而thread2仍然在取队列中的元素导致报错 在这里插入图片描述

(B)解决方法,加入lock(引用类型参数)

在这里插入图片描述 运行结果 在这里插入图片描述

  • (3)如何将线程设置为后台线程

(A)为什么设置为后台线程

因为当新开线程是while死循环时,若此时该线程为前台线程,那么将会导致进程无法正常关闭 而设置为后台线程则会避免这个情况,因为在前台线程关闭时,后台线程会自动关闭

(B)怎么设置

在这里插入图片描述

3、线程的终止及休眠

  • (1)线程休眠:Thread.sleep()

参数为整型,单位是ms,其中1000ms = 1s

  • (1)线程终止

(a)等待线程执行完毕Thread.Join()

在这里插入图片描述

(b)通过bool终止线程

通过一个bool类型的线程结束信号来进行线程的终止 在这里插入图片描述 运行结果 在这里插入图片描述

4、完整代码

  • 线程相关的完整代码

using System.Security.Cryptography.X509Certificates;

namespace Article_8_多线程
{
class Program
{
//定义一个bool类型的线程结束信号
static bool stopThread = false;

#region 一.线程的基础概念
//(1)进程:
//(2)线程:线程是操作系统能进行运算调度的最小单位,线程包含在进程中,是进程实际运行单位

#endregion

#region 2.线程的创建
//(1)线程类 Thread,需要引用命名空间 using System.Threading
//(2)创建线程实列 Thread t = new Thread(传入一个委托)
// (a)该线程要执行的内容要封装在函数之中

static Thread t = new Thread(() =>
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
Console.WriteLine("我是线程t中的逻辑,标识为{0}",i);
}
Console.WriteLine("===线程t运行结束===");
});
static Thread t2 = new Thread((object o) =>
{
Console.WriteLine("参数为{0}",o);
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
Console.WriteLine("我是线程t2中的逻辑,标识为{0}", i);
}
Console.WriteLine("===线程t2运行结束===");
});
#endregion
#region 3.线程的运行
public static void Main(string[] args)
{
//(1)线程的运行 t.Start()
Console.WriteLine("===主线程开始运行===");
// (a)无参
//t.Start();//线程t开始运行
// (b)有参
//t2.Start(1);

//(2)在多线程中,线程之间会共享数据
// 因此可能会出现线程之前出现串联的现象,如在下述队列中,可能会出现同时取出同一个的元素
// 解决方法,加lock(引用类型参数)
Queue<string> queue = new Queue<string>();
queue.Enqueue("a");
queue.Enqueue("b");
queue.Enqueue("c");
queue.Enqueue("d");
queue.Enqueue("e");
queue.Enqueue("f");
queue.Enqueue("g");
queue.Enqueue("h");
queue.Enqueue("i");

//加锁,首先定义一个引用类型变量
string queueLock = "";

Thread thread1 = new Thread(() =>
{
Console.WriteLine("===线程thread1启动===");
//其次,在对应逻辑处加上lock
lock (queueLock)
{
while (queue.Count > 0)
{
Thread.Sleep(5);
string item = queue.Dequeue();
Console.WriteLine($"线程thread1 取出:{item} | 剩余元素数:{queue.Count}");
}
}
Console.WriteLine("===线程thread1结束===");
});
Thread thread2 = new Thread(() =>
{
Console.WriteLine("===线程thread2启动===");
lock (queueLock)
{
while (queue.Count > 0)
{
Thread.Sleep(5);
string item = queue.Dequeue();
Console.WriteLine($"线程thread2 取出:{item} | 剩余元素数:{queue.Count}");
}
}
Console.WriteLine("===线程thread2结束===");
});
thread1.Start();
thread2.Start();
//(3)如何将线程设置为后台线程
// (a)为什么设置为后台线程
// 因为当新开线程是while死循环时,若此时该线程为前台线程,那么将会导致进程无法正常关闭
// 而设置为后台线程则会避免这个情况,因为在前台线程关闭时,后台线程会自动关闭
// (b)怎么设置
//法一:线程实列化时设置
Thread t3 = new Thread(() => { }) { IsBackground=true};
//法二:实列化后设置
t3.IsBackground=true;

#region 3.线程的终止及休眠
//(a)等待线程执行完毕Thread.Join()
thread1.Join();
thread2.Join();
Console.WriteLine();
//(b)通过bool终止线程
Thread bool_End_Theard = new Thread(() =>
{
int count = 0;
Console.WriteLine("bool_End_Theard:开始执行");

// 循环执行,每次检查停止标志
while (!stopThread)
{
Console.WriteLine("bool_End_Theard:正在执行,计数="+count);
count++;
Thread.Sleep(500);
}
// 检测到停止信号退出
Console.WriteLine("bool_End_Theard:检测到停止信号,退出");
});

Console.WriteLine("===== 演示:通过bool标志位终止线程 =====");
bool_End_Theard.Start();
Thread.Sleep(3000);
stopThread = true;//将线程终止信号设为true
bool_End_Theard.Join();

//(c)通过Thread.Interrupt终止

#endregion
}
#endregion

}
}

赞(0)
未经允许不得转载:171主机测评 » C#学习08 多线程
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址