.NET 5.0项目修改配置键名后Program类类型初始化器抛出异常求助
问题诊断
从你的报错栈可以精准定位问题:
---> System.ArgumentNullException: Value cannot be null. (Parameter 's') at System.Int32.Parse(String s) at MailServis.Program..cctor() in C:\Users\djcumbaj\source\repos\MailServis\Program.cs:line 21
核心原因是**ConfigurationManager.AppSettings.Get("VrijemeUMiliSekundama")返回了null**,导致Int32.Parse触发空引用异常。结合你修改过配置键名称的操作,大概率是:
- 你把
VrijemeUMiliSekundama这个配置键重命名为更可读的名称,但代码里没同步更新; - 或者不小心从
app.config中删除了这个配置项; - 也可能是键名出现了拼写/大小写误差(虽然.NET配置键大小写不敏感,但尽量保持完全一致更稳妥)。
你测试直接写死文件路径后邮件能正常读取,但Timer仍抛出相同异常,也验证了问题不在邮件路径配置,而在定时器间隔的配置键上。
解决方案
1. 修复配置键匹配问题
打开你的app.config文件:
- 如果
VrijemeUMiliSekundama被重命名了(比如改成IntervalTimerUMiliSekundama),请同步修改代码中读取的键名; - 如果配置项丢失,重新添加它:
<add key="VrijemeUMiliSekundama" value="你的定时器间隔数值" />
2. 重构配置读取逻辑,避免提前初始化异常
静态字段初始化阶段的异常很难排查,还会直接导致类加载失败。建议把配置读取和验证逻辑移到Main方法中,用更安全的方式处理:
class Program { public static int i = 0; public static Timer aTimer; // 先不初始化,留到Main中处理 static void Main(string[] args) { var logger = NLog.LogManager.GetCurrentClassLogger(); logger.Info("Aplikacija je pokrenuta"); // 读取并验证定时器间隔配置 string vrijemeConfig = ConfigurationManager.AppSettings.Get("VrijemeUMiliSekundama"); if (string.IsNullOrEmpty(vrijemeConfig)) { logger.Error("Konfiguracijski ključ 'VrijemeUMiliSekundama' nije pronađen ili je prazan!"); Console.ReadKey(); return; } if (!int.TryParse(vrijemeConfig, out int vrijemeUMiliSekundama)) { logger.Error("Vrijednost za 'VrijemeUMiliSekundama' nije valjan cijeli broj!"); Console.ReadKey(); return; } // 读取并验证邮件路径配置 string lokacijaMailova = ConfigurationManager.AppSettings.Get("LokacijaExportanihMailAdresa"); if (string.IsNullOrEmpty(lokacijaMailova)) { logger.Error("Konfiguracijski ključ 'LokacijaExportanihMailAdresa' nije pronađen ili je prazan!"); Console.ReadKey(); return; } // 其他配置项也建议做类似验证 string posiljatelj = ConfigurationManager.AppSettings.Get("Posiljatelj"); string subjekt = ConfigurationManager.AppSettings.Get("Predmet"); // ... 其他配置读取 try { var mailovi = File.ReadAllLines(lokacijaMailova); aTimer = new Timer(vrijemeUMiliSekundama); aTimer.Elapsed += (sender, e) => OnTimedEvent(sender, e, logger, mailovi, i++); aTimer.Start(); Console.ReadKey(); } catch (Exception ex) { logger.Error(ex, "Došlo je do greške prilikom pokretanja aplikacije"); Console.ReadKey(); } } }
这种方式的优势:
- 提前捕获配置错误,给出明确的日志提示;
- 不会因单个配置项问题导致整个类加载失败;
- 用
int.TryParse替代Int32.Parse,避免格式错误引发的异常。
3. 全面检查配置项一致性
趁这个机会,把代码中所有读取的配置键和app.config里的内容逐一比对,确保Posiljatelj、Predmet等其他键也没有因重命名导致的不匹配问题,避免后续再踩类似的坑。
内容的提问来源于stack exchange,提问作者Dominik Cumbaj
相关产品推荐
相关产品推荐

