进程是操作系统资源分配的基本单位,拥有独立内存空间和安全上下文;线程是进程内调度最小单元,共享堆内存与全局变量,需同步机制保障线程安全。

进程是操作系统分配资源的基本单位
一个 Process 对应一个独立的内存空间、句柄表和安全上下文。你启动一个 dotnet MyApp.dll,系统就创建一个新进程;再开一个,就是另一个完全隔离的进程。它们之间默认不共享内存,通信得靠 NamedPipe、MemoryMappedFile 或 WCF 这类跨进程机制。
常见误区是以为“多开几个控制台窗口跑同一个程序,它们能互相改对方的变量”——不能。每个窗口背后是独立 Process,static 字段也互不影响。
线程是进程内执行代码的最小调度单元
同一进程里的多个 Thread(或 Task)共享堆内存、全局变量和文件句柄。比如你在 Main 方法里声明一个 static List,所有线程都能读写它——但这也意味着必须手动加锁(lock、Monitor 或 ConcurrentQueue),否则容易出现数据错乱。
注意:.NET 中推荐用 Task 而不是裸 Thread,因为 ThreadPool 会复用线程,避免频繁创建销毁的开销。直接 new Thread 只在需要长时间独占、设置特定优先级或避免被线程池回收时才用。
-
Thread启动开销大,Task.Run更轻量 - UI 线程(如 WinForms/WPF 的主线程)不能被
Thread.Sleep阻塞,否则界面冻结;要用await Task.Delay -
async/await不一定新建线程,它只是释放当前线程去干别的事,回调时可能回到原线程(尤其 UI 上下文)
看任务管理器就能直观区分
打开 Windows 任务管理器 → “详细信息”页,每一行是一个 Process(比如 devenv.exe、chrome.exe)。右键 → “转到服务”或“转到进程”,能看到它下面挂了多少个线程(列名是 “线程数”)。这个数字是该进程内所有线程的总和,包括主线程、GC 线程、ThreadPool 线程、Timer 回调线程等。
如果你用 Process.GetCurrentProcess().Threads.Count,拿到的就是当前进程的线程总数,不是你代码里显式 new Thread() 的个数。
BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录
什么时候该用进程,什么时候该用线程
选进程:需要强隔离(比如插件沙箱、用户代码执行)、崩溃不能影响主程序、或必须加载不同版本的同一 DLL(如两个插件依赖不同版 Newtonsoft.Json)。
选线程(或 Task):同一业务逻辑并行处理(如批量下载、图像处理)、响应式 UI、I/O 等待期间不阻塞主线程。
特别注意:AppDomain 在 .NET Core/.NET 5+ 已被移除,不能再靠它做隔离——现在只有进程级隔离最可靠。
var p = Process.Start("notepad.exe");
Console.WriteLine($"新进程 ID: {p.Id}");
// 此时 notepad 和当前程序完全无关,杀掉它也不会影响本程序
线程间共享内存是双刃剑:快,但也容易出竞态。别指望“我只读不写”就绝对安全——没有 volatile 或内存屏障,CPU 可能缓存旧值;没加锁的写操作也可能被重排序。真要共享,优先选 ConcurrentDictionary 这类线程安全集合,而不是自己上 lock。









