马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在 .NET情况下,多线程编程主要有 Thread ThreadPool Task Parallel BackgroundWorker 等几种,另有一个与多线程干系的:异步编程 async/await ,值得夸大的是,异步编程不等于多线程 。当然,这几种多线程编程的方式并不是独立开的,在底层的封装有肯定的接洽。
1. Thread
1.1 底子应用
引用Thread的命名空间
- using System;
- using System.Threading;
复制代码 直接创建线程举行启动
- static void Main()
- {
- // 创建一个新线程
- Thread thread = new Thread(DoWork);
- thread.Start(); // 启动线程
- // 主线程继续执行
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是主线程打印: " + i);
- Thread.Sleep(500);
- }
- Console.ReadKey();
- }
- static void DoWork()
- {
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是自主创建的线程打印: " + i);
- Thread.Sleep(500);
- }
- }
复制代码 调试结果:
- 这是自主创建的线程打印: 0
- 这是主线程打印: 0
- 这是自主创建的线程打印: 1
- 这是主线程打印: 1
- 这是主线程打印: 2
- 这是自主创建的线程打印: 2
- 这是主线程打印: 3
- 这是自主创建的线程打印: 3
- 这是主线程打印: 4
- 这是自主创建的线程打印: 4
- 这是主线程打印: 5
- 这是自主创建的线程打印: 5
- 这是主线程打印: 6
- 这是自主创建的线程打印: 6
- 这是主线程打印: 7
- 这是自主创建的线程打印: 7
- 这是主线程打印: 8
- 这是自主创建的线程打印: 8
- 这是主线程打印: 9
- 这是自主创建的线程打印: 9
复制代码 可以发现,主线程和自己创建的线程各干各的,互不耽搁。
1.2 线程入参
如果我在启动线程时想给他一个参数呢?这样搞:
1. 在委托方法设置参数
- static void Main()
- {
- // 创建一个新线程
- Thread thread = new Thread(DoWork);
- thread.Start("子线程启动啦"); // 启动线程
- // 主线程继续执行
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是主线程打印: " + i);
- Thread.Sleep(500);
- }
- Console.ReadKey();
- }
- static void DoWork(object obj)
- {
- // 将传入的 object 类型参数转换为实际类型
- string message = (string)obj;
- Console.WriteLine($"Received message in Main thread: {message}");
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是自主创建的线程打印: " + i);
- Thread.Sleep(500);
- }
- }
复制代码 调试结果:
- 这是主线程打印: 0
- Received message in Main thread: 子线程启动啦
- 这是自主创建的线程打印: 0
- 这是自主创建的线程打印: 1
- 这是主线程打印: 1
- 这是主线程打印: 2
- 这是自主创建的线程打印: 2
- 这是主线程打印: 3
- 这是自主创建的线程打印: 3
- 这是主线程打印: 4
- 这是自主创建的线程打印: 4
- 这是主线程打印: 5
- 这是自主创建的线程打印: 5
- 这是主线程打印: 6
- 这是自主创建的线程打印: 6
- 这是主线程打印: 7
- 这是自主创建的线程打印: 7
- 这是自主创建的线程打印: 8
- 这是主线程打印: 8
- 这是主线程打印: 9
- 这是自主创建的线程打印: 9
复制代码 2. 使用Lambda表达式
- static void Main()
- {
- // 创建一个新线程
- // 使用 Lambda 表达式创建线程并传递参数
- Thread thread = new Thread(() =>
- {
- DoWork("子线程又又又启动啦");
- });
- // 启动线程
- thread.Start();
- // 主线程继续执行
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是主线程打印: " + i);
- Thread.Sleep(500);
- }
- Console.ReadKey();
- }
- static void DoWork(object obj)
- {
- // 将传入的 object 类型参数转换为实际类型
- string message = (string)obj;
- Console.WriteLine($"Received message in Main thread: {message}");
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是自主创建的线程打印: " + i);
- Thread.Sleep(500);
- }
- }
复制代码 调试运行结果:
- 这是主线程打印: 0
- Received message in Main thread: 子线程又又又启动啦
- 这是自主创建的线程打印: 0
- 这是主线程打印: 1
- 这是自主创建的线程打印: 1
- 这是主线程打印: 2
- 这是自主创建的线程打印: 2
- 这是主线程打印: 3
- 这是自主创建的线程打印: 3
- 这是主线程打印: 4
- 这是自主创建的线程打印: 4
- 这是主线程打印: 5
- 这是自主创建的线程打印: 5
- 这是主线程打印: 6
- 这是自主创建的线程打印: 6
- 这是主线程打印: 7
- 这是自主创建的线程打印: 7
- 这是主线程打印: 8
- 这是自主创建的线程打印: 8
- 这是主线程打印: 9
- 这是自主创建的线程打印: 9
复制代码 2. ThreadPool
System.Threading.ThreadPool 是一个线程池,用于管理和复用线程,得当处理大量短生命周期的任务。着实这个是对Thread的封装,从某种程度上讲节省了步伐运行的开销。
- static void Main()
- {
- // 将任务加入线程池
- ThreadPool.QueueUserWorkItem(DoWork);
- // 主线程继续执行
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是主线程打印: " + i);
- Thread.Sleep(500);
- }
- Console.ReadKey();
- }
- static void DoWork(object obj)
- {
- // 将传入的 object 类型参数转换为实际类型
- string message = (string)obj;
- Console.WriteLine($"Received message in Main thread: {message}");
- for (int i = 0; i < 10; i++)
- {
- Console.WriteLine("这是自主创建的线程打印: " + i);
- Thread.Sleep(500);
- }
- }
复制代码 运行调试结果
- 这是主线程打印: 0
- Received message in Main thread:
- 这是自主创建的线程打印: 0
- 这是自主创建的线程打印: 1
- 这是主线程打印: 1
- 这是主线程打印: 2
- 这是自主创建的线程打印: 2
- 这是主线程打印: 3
- 这是自主创建的线程打印: 3
- 这是主线程打印: 4
- 这是自主创建的线程打印: 4
- 这是主线程打印: 5
- 这是自主创建的线程打印: 5
复制代码 3. Task
System.Threading.Tasks.Task 是基于任务的异步编程模型(TAP),是对ThreadPool的进一步封装,提供了更高级的功能。感觉套娃是微软的强项哈哈。
- static void Main()
- {
- // 创建一个任务并启动
- Task task = Task.Run(() => DoWork());
- // 主线程继续执行
- for (int i = 0; i < 4; i++)
- {
- Console.WriteLine("这是主线程打印: " + i);
- Task.Delay(500).Wait();
- }
- task.Wait(); // 等待任务完成
- Console.ReadKey();
- }
- static void DoWork()
- {
-
- for (int i = 0; i < 7; i++)
- {
- Console.WriteLine("这是自主创建的线程打印: " + i);
- Thread.Sleep(500);
- }
- }
复制代码 调试执行:
- 这是主线程打印: 0
- 这是自主创建的线程打印: 0
- 这是自主创建的线程打印: 1
- 这是主线程打印: 1
- 这是自主创建的线程打印: 2
- 这是主线程打印: 2
- 这是主线程打印: 3
- 这是自主创建的线程打印: 3
- 这是自主创建的线程打印: 4
- 这是自主创建的线程打印: 5
- 这是自主创建的线程打印: 6
复制代码 从综合性能和实战经验来看,Task应该是应用最多的,主要表现在以下几个特点
- 支持任务并行和异步操作。
- 可以获取任务的执行结果(通过Task<TResult>)。
- 支持任务取消、延续和非常处理。
4. Parallel
System.Threading.Tasks.Parallel 提供了简朴的并行循环和并行任务执行。
- // 并行执行循环
- Parallel.For(0, 5, i =>
- {
- Console.WriteLine("Parallel thread: " + i);
- Task.Delay(500).Wait();
- });
复制代码 调试运行:
- Parallel thread: 3
- Parallel thread: 0
- Parallel thread: 4
- Parallel thread: 1
- Parallel thread: 2
复制代码
这种模式适用于任务并行分发的场景,简朴,高效。
5. BackgroundWorker
System.ComponentModel.BackgroundWorker 是一个用于在后台执行任务的组件,得当在UI应用步伐中使用。
代码示例:
- static void Main()
- {
- BackgroundWorker worker = new BackgroundWorker();
- worker.DoWork += DoWork;
- worker.RunWorkerCompleted += WorkCompleted;
- worker.RunWorkerAsync(); // 启动后台任务
- Console.WriteLine("Main thread continues...");
- Console.ReadKey();
- }
- static void DoWork(object sender, DoWorkEventArgs e)
- {
- for (int i = 0; i < 5; i++)
- {
- Console.WriteLine("工作线程: " + i);
- System.Threading.Thread.Sleep(500);
- }
- }
- static void WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- Console.WriteLine("任务完成.");
- }
复制代码 运行结果:
- Main thread continues...
- 工作线程: 0
- 工作线程: 1
- 工作线程: 2
- 工作线程: 3
- 工作线程: 4
- 任务完成.
复制代码
6. async/await
async/await不是多线程。只是和多线程干系,详细来说是和Task直接干系。
代码示例1:
- static async Task Main()
- {
- Console.WriteLine("主线程启动.");
- // 异步调用
- await DoWorkAsync();
- Console.WriteLine("主线程完成.");
- Console.ReadKey();
- }
- static async Task DoWorkAsync()
- {
- for (int i = 0; i < 5; i++)
- {
- Console.WriteLine("异步方法执行: " + i);
- await Task.Delay(500);
- }
- }
复制代码 运行结果:
- 主线程启动.
- 异步方法执行: 0
- 异步方法执行: 1
- 异步方法执行: 2
- 异步方法执行: 3
- 异步方法执行: 4
- 主线程完成.
复制代码 大概这样写:
- static async Task DoWorkAsync()
- {
- for (int i = 0; i < 5; i++)
- {
- await Task.Run(() =>
- {
- Console.WriteLine("异步方法执行: " + i);
- Task.Delay(500);
- });
- }
- }
复制代码 关于异步编程,在杨中科的书里学了一点:第2章 .NETCore异步编程 C#异步编程 关键字async/await用法
DeepSeek总结:
种类适用场景优点缺点Thread需要精细控制线程的场景直接控制线程生命周期手动管理线程,开销较大ThreadPool大量短生命周期任务线程复用,减少开销不得当长时间任务Task异步编程和任务并行功能强盛,支持任务结果和非常处理需要理解异步编程模型Parallel简朴的并行循环简化并行编程不得当复杂任务async/await异步编程,避免阻塞主线程代码简便,易于理解需要理解异步编程模型BackgroundWorkerUI应用步伐中的后台任务支持进度陈诉和取消操作功能相对简朴 7. 线程间的通讯
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |