项目 5 补齐:旧版线程 API(Suspend / Resume / Abort)与 ListBox

- 编译时把 Thread 的 Suspend / Resume / Abort、ThreadState、Sleep、new Thread 改写成平台的
  协作式实现:被挂起或终止的线程在 Sleep、后台改控件、调设备类库、弹提示框时停下或结束;
  ThreadStateException 等行为与 .NET Framework 一致;编辑器不再提示"已过时"
- ListBox:列表项、单选、SelectedIndexChanged 先于 Click、删除选中项后取消选中;
  ComboBox 与 ListBox 共用 ListControl 和列表项集合;设计器工具箱加"列表框"
- 评分规则的"包含"对列表框检查所有列表项
- 示例:项目 5 任务 2(烟雾,线程)、任务 3(推送灾情,二维数组、两个窗体、ListBox),
  参考答案修正书上直接 Abort 挂起线程、烟雾记成"发现火情"的问题
- 一直不换行的 Console 输出攒满 4096 字符先发出,避免占满内存
- 测试:旧版线程 API、ListBox 事件顺序、两个示例的端到端和评分测试

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-22 20:33:12 +08:00
1 parent 8a92354fe4
commit 91b39603a2
36 files changed
+1653 -105

No files matched your search

+17 -1
View File
@@ -31,7 +31,7 @@ async function prepare(id: string, name: string, edit?: { file: string; from: st
describe('参考答案全部通过', async () => {
const ids = (await Array.fromAsync(new Bun.Glob('*/checks.yaml').scan({ cwd: SAMPLES }))).map((p) => p.split('/')[0]).sort()
test('每个示例都有评分规则', () => expect(ids.length).toBe(10))
test('每个示例都有评分规则', () => expect(ids.length).toBe(12))
for (const id of ids) {
test(id, async () => {
const result = await grade(await prepare(id, id), await checksOf(id))
@@ -80,6 +80,22 @@ describe('改坏的代码', () => {
expect(stop.message).toStartWith('期望 txt_time 不再更新时间(定时器应已停止),实际从')
}, 60000)
test('关闭时忘了挂起线程', async () => {
const id = 'p5-t2-烟雾'
const dir = await prepare(id, 'thread', { file: 'Form1.cs', from: 'thd.Suspend();//挂起线程', to: '' })
const result = await grade(dir, await checksOf(id))
const stop = result.results.find((r) => r.title === '再点按钮能关闭串口、挂起线程,再次打开时线程继续')!
expect(stop.passed).toBe(false)
expect(stop.message).toStartWith('期望 txt_time 不再更新时间(线程应已挂起),实际从')
}, 60000)
test('历史灾情窗体没有把数组里的记录加入列表框', async () => {
const id = 'p5-t3-推送灾情'
const dir = await prepare(id, 'listbox', { file: 'Form2.cs', from: 'lstbRecored.Items.Add(', to: 'Console.WriteLine(' })
const result = await grade(dir, await checksOf(id))
expect(result.results[2]).toMatchObject({ passed: false, message: '期望 lstbRecored 列表里有"发现火情"的记录,实际列表是空的' })
}, 60000)
test('报警灯接错了 DO 口', async () => {
const id = 'p4-t3-报警灯'
const dir = await prepare(id, 'relay', { file: 'Form1.cs', from: 'DeviceCtrlHelper.adam4150Helper.OnOff(0, IsOpen);', to: 'DeviceCtrlHelper.adam4150Helper.OnOff(1, IsOpen);' })