如何为C#程序设置虚拟内存使用上限,超限时终止并抛出异常
给C#程序设置运行时内存上限并超限终止的方案
嘿,针对你这个大型C#程序要设置内存上限、超限自动终止的需求,我来给你几个实用的方案——毕竟手动在各处加PrivateMemorySize检查确实太折腾了,大型项目里根本顾不过来,很容易遗漏场景。
1. 后台线程全局监控(最省心的实现方式)
这个思路和你之前看到的循环检查类似,但我们把监控逻辑封装成一个独立的后台线程,程序启动时就跑起来,全程自动监控,完全不用在业务代码里埋点。
示例代码:
using System; using System.Threading; class MemoryMonitor { private readonly long _maxMemoryBytes; private readonly Timer _monitorTimer; public MemoryMonitor(long maxMemoryMb) { // 强制最低100Mb,转换为字节单位 _maxMemoryBytes = Math.Max(maxMemoryMb * 1024 * 1024, 100 * 1024 * 1024); // 每隔1秒检查一次(可根据需求调短,比如100ms,响应更快但略增CPU开销) _monitorTimer = new Timer(CheckMemoryUsage, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); } private void CheckMemoryUsage(object state) { var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); // 这里可以选PrivateMemorySize64(私有内存,不包含共享部分)或WorkingSet64(物理内存占用),按需选择 long currentMemory = currentProcess.PrivateMemorySize64; if (currentMemory > _maxMemoryBytes) { _monitorTimer.Dispose(); // 先停掉定时器,避免重复触发 // 抛出自定义异常,或者直接终止程序,看你需求 throw new OutOfMemoryException($"内存超限!当前使用:{currentMemory / (1024*1024)}Mb,限制:{_maxMemoryBytes/(1024*1024)}Mb"); // 要是不想抛异常,直接终止也可以:Environment.Exit(1); } } public void StopMonitoring() { _monitorTimer?.Dispose(); } } // 程序启动时初始化监控 class Program { static void Main(string[] args) { // 从命令行参数读取内存限制,比如启动时传"200"就是200Mb,默认用最低100Mb long maxMemoryMb = 100; if (args.Length > 0 && long.TryParse(args[0], out var inputMb)) { maxMemoryMb = inputMb; } // 使用using确保监控器能正确释放 using var memoryMonitor = new MemoryMonitor(maxMemoryMb); // 这里放你的业务逻辑代码 // 举个例子模拟内存暴涨: var memoryHog = new System.Collections.Generic.List<byte[]>(); try { while (true) { memoryHog.Add(new byte[1024 * 1024]); // 每次加1Mb Console.WriteLine($"当前内存使用:{System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64/(1024*1024)}Mb"); Thread.Sleep(500); } } catch (OutOfMemoryException ex) { Console.WriteLine(ex.Message); Environment.Exit(1); } } }
小提示:
- 检查间隔可以灵活调整:如果对内存超限的响应速度要求高,就把间隔设短(比如100ms),但会增加一点点CPU占用,根据你的程序负载平衡就行。
- 选对内存指标:
PrivateMemorySize64是进程独占的内存,WorkingSet64是当前实际占的物理内存,你可以根据自己的监控需求选。
2. 操作系统层面的限制(适合部署场景)
如果你的程序是部署在服务器上,也可以直接用操作系统的工具来限制进程内存,这样更严格,不用改代码:
- Windows:用「作业对象(Job Object)」来限制进程内存,C#可以通过P/Invoke调用Windows API实现,不过代码会复杂点,但能做到系统级的强制限制。
- Linux:启动程序前用
ulimit命令,比如ulimit -v 104857600 && dotnet YourApp.dll(100Mb的虚拟内存限制),或者用cgroup做更精细的资源管控,超限后系统会直接终止进程。
为什么不推荐手动在各处加检查?
大型项目里到处埋内存检查不仅繁琐,还容易漏场景,而且会把业务代码和监控代码混在一起,后期维护起来头疼。后台线程监控是非侵入式的,只需要启动时初始化一次,全程自动运行,完美适配你的场景。
最后别忘了强制最低100Mb的限制,代码里一定要做判断,别让用户设置低于这个值,不然程序可能刚启动就挂了。
内容的提问来源于stack exchange,提问作者HariUserX




