Skip to Content
Week 09📋 Week 09 阶段检查

Week 09 - 阶段检查

这一页用来确认 Week 9 有没有真正掌握:数据量变大时能处理,文件能保存,错误能记录,发布后能验收。

本周学习地图

阶段先掌握什么最终能写什么
性能Stopwatch、耗时记录能定位慢在哪里
大列表全部数据和可见数据分开能处理大量商品
文件对话框、路径、取消选择能导入导出文件
持久化JSON 保存和读取能关闭后恢复数据
发布dotnet publish能生成发布目录
日志INFO、WARNING、ERROR能留下排错线索

本周自测项目:可发布的数据工具

从商品管理页面开始补可靠性,至少包含:

  • 使用 Stopwatch 输出搜索或加载耗时。
  • AllProducts 保存全部数据,VisibleProducts 绑定界面。
  • 支持 JSON 保存和读取。
  • 支持选择文件导入或导出。
  • 保存失败时显示错误并写日志。
  • dotnet publish -c Release 生成发布目录。

过关标准:能说明开发运行和发布目录运行有什么不同。

上位机阶段验收:可保存和发布的桌面程序

本周目标: 解决大量数据、配置持久化、导入导出、日志和 Release 发布。

必须亲手完成:

  1. 10000 条模拟记录仍可滚动
  2. JSON 设置重启后恢复
  3. 在未安装 SDK 的目标电脑运行发布包

过关标准: 发布目录完整,异常有日志和用户提示,配置与数据路径明确。

不要只看答案。新建一个空项目重做一次,运行成功后再故意改坏一处并自己排错。

本周流程图

加载全部商品 -> Stopwatch 记录耗时 -> AllProducts 保存完整数据 -> VisibleProducts 绑定界面 -> 文件对话框选择导入或导出路径 -> JSON 保存和读取状态 -> 日志记录错误 -> dotnet publish 生成发布目录

前半部分:本周原理地图

Week 9 的主线是:

程序不能只在开发目录里能跑,还要在数据变多、文件读写、异常发生、发布交付时保持可靠。

这一周不是新增很多孤立知识点,而是把项目从“功能能跑”推进到“能交付、能恢复、能排查”。

这一周的能力地图

能力解决的问题最小判断
性能测量不靠感觉判断慢能用 Stopwatch 打出耗时
大列表处理数据多时界面不卡能区分全部数据和可见数据
文件对话框用户选择文件后读写能处理取消、读取、保存
数据持久化程序关闭后数据不丢能保存 JSON 并读取回来
打包发布生成可运行目录能执行 dotnet publish
错误日志出错后能排查能写 INFO、WARNING、ERROR

功能交付的 6 个检查点

一个功能要进入可交付状态,至少要回答 6 个问题:

  1. 输入是什么。
  2. 处理规则是什么。
  3. 输出结果是什么。
  4. 数据多时会不会一次做太多事。
  5. 失败时用户看到什么。
  6. 失败细节记录在哪里。

如果只能回答前 3 个,说明功能只是跑通了主流程。

如果 6 个都能回答,说明功能已经具备基本交付条件。

本周常见错误和修法

常见错误为什么有问题修法
没测量就优化不知道慢在哪里先用 Stopwatch 记录耗时
列表直接绑定全部数据数据一多界面压力大VisibleProducts 控制当前显示
文件对话框取消后继续读没有文件还继续执行取消时直接 return
JSON 读取不判空反序列化可能返回空值?? new List<T>()
发布后不运行开发目录会掩盖问题从发布目录启动一次
日志只写“出错了”没有排查线索写清动作、对象、异常

本周通过线

达到下面这些,再进入下一周:

  • 能写出 Stopwatch 耗时代码。
  • 能说清 allProductsVisibleProducts 的区别。
  • 能用文件对话框打开和保存文本。
  • 能把列表保存成 JSON,再读取回来。
  • 能执行一次 dotnet publish -c Release -o ./artifacts/publish
  • 能把异常写入日志文件。
  • 能写出一份发布验收清单。

Week 9 必须会用的操作

主题必须会的写法
性能Stopwatch.StartNew()ElapsedMilliseconds
大列表allProductsVisibleProductsTake(100)
搜索WhereContains、刷新可见集合
文件对话框StorageProvider.OpenFilePickerAsyncSaveFilePickerAsync
JSONJsonSerializer.SerializeDeserialize
文件File.ReadAllTextWriteAllTextExists
发布dotnet publish -c Release -o ...
日志时间、级别、动作、异常消息

下半部分:阶段检查完整答案

下面这份程序就是 Week 9 的阶段检查。它不是界面程序,而是用控制台把本周主线压缩到一个可运行文件里。

它会检查 5 件事:

  1. 生成 5000 条数据。
  2. 只处理首屏 100 条。
  3. 保存 JSON。
  4. 读取 JSON。
  5. 故意制造错误并写日志。

检查题:Program.cs

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.Json; string appFolder = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Week09Checkpoint"); Directory.CreateDirectory(appFolder); string jsonPath = Path.Combine(appFolder, "products.json"); string logPath = Path.Combine(appFolder, "app.log"); Task LogAsync(string level, string message, Exception? ex = null) { string detail = ex is null ? message : $"{message}{Environment.NewLine}{ex}"; string line = $"{DateTimeOffset.Now:yyyy-MM-dd HH:mm:ss.fff zzz} [{level}] {detail}{Environment.NewLine}"; return File.AppendAllTextAsync(logPath, line); } var watch = Stopwatch.StartNew(); List<Product> allProducts = Enumerable .Range(1, 5000) .Select(i => new Product($"Product {i:0000}", i * 1.5m)) .ToList(); List<Product> visibleProducts = allProducts .Take(100) .ToList(); await LogAsync("INFO", $"全部商品 {allProducts.Count} 条,当前显示 {visibleProducts.Count} 条"); string json = JsonSerializer.Serialize(visibleProducts, new JsonSerializerOptions { WriteIndented = true }); await File.WriteAllTextAsync(jsonPath, json); await LogAsync("INFO", $"JSON 保存完成:{jsonPath}"); string loadedJson = await File.ReadAllTextAsync(jsonPath); List<Product> loadedProducts = JsonSerializer.Deserialize<List<Product>>(loadedJson) ?? new List<Product>(); watch.Stop(); Console.WriteLine("Week 9 阶段检查"); Console.WriteLine($"全部商品数量:{allProducts.Count}"); Console.WriteLine($"当前显示数量:{visibleProducts.Count}"); Console.WriteLine($"读取回来数量:{loadedProducts.Count}"); Console.WriteLine($"耗时:{watch.ElapsedMilliseconds}ms"); Console.WriteLine($"JSON 文件:{jsonPath}"); Console.WriteLine($"日志文件:{logPath}"); try { string missingPath = Path.Combine(appFolder, "missing.json"); await File.ReadAllTextAsync(missingPath); } catch (Exception ex) { await LogAsync("ERROR", "读取 missing.json 失败", ex); Console.WriteLine("错误检查:已捕获异常并写入日志。"); } record Product(string Name, decimal Price);

运行命令

dotnet new console -n Week09Checkpoint cd Week09Checkpoint

把上面的代码放进 Program.cs,然后执行:

dotnet run

正确运行结果

结果里的耗时会因电脑不同而不同,但数量必须一致:

Week 9 阶段检查 全部商品数量:5000 当前显示数量:100 读取回来数量:100 耗时:若干 ms JSON 文件:... 日志文件:... 错误检查:已捕获异常并写入日志。

这份答案检查了哪些能力

检查点对应代码合格标准
性能测量Stopwatch.StartNew()能看到耗时
大列表处理Take(100)不一次处理全部显示数据
持久化JsonSerializer.Serialize能保存 JSON
数据恢复Deserialize<List<Product>>能读取回来 100 条
错误处理try/catch不让程序直接崩溃
日志LogAsync("ERROR", ...)错误细节写入文件

发布检查答案

阶段检查还要补一份发布命令和验收清单。

最小发布命令

dotnet build dotnet publish -c Release -o ./artifacts/publish

macOS Apple Silicon

dotnet publish -c Release -r osx-arm64 --self-contained true -o ./artifacts/osx-arm64

Windows x64

dotnet publish -c Release -r win-x64 --self-contained true -o ./artifacts/win-x64

发布验收清单

发布目录检查: 1. 发布目录存在。 2. 主程序文件存在。 3. 依赖文件存在。 4. runtimeconfig 文件存在。 启动检查: 1. 从发布目录启动程序。 2. 主窗口能显示。 3. 主流程能执行。 4. 资源和样式没有丢失。 数据检查: 1. 能保存 JSON。 2. 能读取 JSON。 3. 关闭后再打开,数据能恢复。 错误检查: 1. 错误操作不会直接崩溃。 2. 用户能看到简短提示。 3. 日志文件能看到详细异常。 交付检查: 1. 版本号写清楚。 2. 发布日期写清楚。 3. 是否需要 .NET Runtime 写清楚。 4. 目标系统写清楚。

最终通过标准

这一页通过时,应该能做到:

  1. 运行阶段检查程序,数量结果正确。
  2. 打开 JSON 文件,能看到商品数据。
  3. 打开日志文件,能看到 INFO 和 ERROR。
  4. 说清 visibleProducts 为什么不是 allProducts
  5. 说清用户提示和日志的区别。
  6. 写出至少一条发布命令和一份验收清单。

Week 9 的重点不是“记住某个 API”,而是形成一条完整判断路线:先测量,再控制数据量;要保存,就明确路径;会失败,就捕获并记录;要交付,就从发布目录重新验收。