C# 多线程并行编程示例:Task 异步执行与主线程同步

温以宁
温以宁
发布时间:2026-10-14| 6人浏览过
原创

本文提供了一个完整的C#多线程并行编程示例,演示如何利用Task类创建并运行多个并发任务,同时介绍如何确保主程序在后台任务全部完成后才优雅退出,避免进程提前终止导致的部分日志丢失问题。

目标与原理

在开发桌面或服务器端应用时,经常需要执行耗时操作而不阻塞用户界面或主流程。C#中的 System.Threading.Tasks.Task 是基于线程池的强大抽象。本示例旨在展示:

  • 如何通过匿名委托启动轻量级后台任务。
  • 如何处理多线程环境下的资源竞争(虽然本例为只读演示)。
  • 如何同步等待任务完成以确保程序正常关闭。

准备条件

  1. 开发环境:Visual Studio 2019 或更高版本(支持 .NET Framework 4.5+ 或 .NET Core/5/6/7/8)。
  2. 项目类型:C# 控制台应用程序(Console App)。
  3. 核心依赖:需引入 System, System.Collections.Generic, System.Linq, System.Threading, System.Threading.Tasks 命名空间。

第1步:定义耗时模拟方法

为了体现并行效果,我们需要一个能产生“等待”行为的方法。以下代码模拟了一个带有消息标识和循环间隔的任务逻辑。

using System;
using System.Threading;

namespace ParallelTest
{
    class Program
    {
        // 模拟一个带日志的耗时操作
        private static int Timed_Message(string arg_Message, int arg_Interval)
        {
            for (int i = 0; i < 10; i++)
            {
                // 向控制台写入当前状态
                Console.WriteLine("Source {0} - Cycle {1} for Interval {2}", arg_Message, i, arg_Interval);
                
                // 模拟耗时工作,单位为秒
                Thread.Sleep(1000 * arg_Interval);
            }
            
            Console.WriteLine("{0} - Complete", arg_Message);
            return 0;
        }
    }
}

该方法的目的是:
1. 打印带有来源标识 arg_Message 的周期性日志。
2. 通过 Thread.Sleep 控制每个周期的间隔时间 arg_Interval。
3. 循环10次后标记该特定任务源已完成。

第2步:启动并行 Task 任务

在 Main 方法中,我们不使用传统的 Thread 类,而是使用更高级别的 Task API来管理并发。这允许我们利用 .NET 的线程池优化性能。

        static void Main(string[] args)
        {
            int RetCode = 0;

            // 任务1:每隔4秒打印一次消息 "Five"
            // 注意:直接传递闭包引用局部变量 RetCode 需注意作用域,此处仅为演示结构
            Task taskOne = new Task(() => RetCode = Timed_Message("Five ", 4));
            taskOne.Start();

            // 任务2:每隔2秒打印一次消息 "Three"
            Task taskTwo = new Task(() => RetCode = Timed_Message("Three ", 2));
            taskTwo.Start();

            // ... (后续步骤见下文) ...
        }

在此处,我们启动了两个不同的后台任务:
- taskOne:对应参数 ("Five ", 4),意味着每轮延迟4秒。
- taskTwo:对应参数 ("Three ", 2),意味着每轮延迟2秒。

这两个任务将在不同的线程上几乎同时开始执行,体现了并行性。

第3步:同步等待与程序退出

如果不在 Main 方法末尾进行干预,当主线程运行结束时,JIT编译器和操作系统可能会强制杀掉正在运行的子任务。为了避免这种情况,必须显式地等待它们完成。

            // 等待用户输入以保持在前台观察结果
            Console.WriteLine("Press enter to finish after both [Complete] messages appear.");
            Console.ReadLine();
        }

这里使用了 Console.ReadLine() 作为简易的同步屏障。在实际的生产环境中,推荐使用 Task.WaitAll(taskOne, taskTwo) 或者更具现代感的 await Task.WhenAll(...) (如果使用的是 async/await 模式),以确保在主线程退出前所有后台逻辑均已安全落地。

运行结果分析

编译并运行上述代码后,控制台将混合输出两个任务的日志。由于是两个独立的线程交替获取 CPU 时间片,输出顺序可能因系统负载而异,但遵循以下规律:

  • 交错输出:你会看到 Five 和 Three 的消息混杂在一起。例如:Five - Cycle 0 之后可能是 Three - Cycle 0 接着是 Three - Cycle 1。
  • 速度差异:因为 Three 的间隔是2秒而 Five 是4秒,所以在相同时间段内,Three 会产出更多的日志行。
  • 结束顺序:较短间隔的任务通常会先打印 [SourceName] - Complete 标志。

典型输出片段如下:

Press enter to finish after both [Complete] messages appear.
Source Five  - Cycle 0 for Interval 4
Source Three - Cycle 0 for Interval 2
Source Three - Cycle 1 for Interval 2
Source Five  - Cycle 1 for Interval 4
... (中间省略部分输出) ...
Three - Complete
Five - Complete

关键注意事项

  1. 异常处理:在真实应用中,若后台任务抛出未捕获异常,默认行为可能会导致整个进程崩溃。建议使用 try-catch 块包裹任务逻辑或使用 Task.ContinueWith 来处理错误回调。
  2. 共享数据保护:本例中 RetCode 虽然在多任务间被修改,但由于最后仅用于赋值且未参与复杂计算,故未加锁。涉及写操作的变量时应使用 Interlocked 类或 lock 语句以防止竞态条件。
  3. CancellationToken:长时间运行的任务应支持取消令牌(CancellationToken),以便外部可以主动终止挂起的操作。

总结

通过此示例,我们掌握了使用 System.Threading.Tasks.Task 实现基础并行处理的模式。这对于提升 IO 密集型或 CPU 密集型批处理任务的效率非常有效。以上就是 C# 并行编程中使用 Task 进行多线程异步处理的详细内容,更多关于 C# 并发编程进阶的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。