给七亿批量远程管理工具加自动清理传输队列这个功能,难点不在"清",在判断什么时候不能清。

需求提过来只有一句话:传完自动清掉,别让人再点一次「清除」。听起来是三四行代码的事,做的时候才发现,清早了用户看不到结果,清晚了等于没做,清错了会把正在跑的任务一起抹掉。最后落地的规则是这样的:队列里所有项都成功结束后,停 1.5 秒,等那句「✅ 全部完成」在屏幕上留住,再清空已完成项、把队列面板收起来。

那 1.5 秒不是随便拍的。最初我写的是完成即清,测试的时候自己都懵——文件明明传上去了,界面一闪,队列没了,我盯着空面板愣了两秒,还得去远端 ls 确认一遍。用户只会比我更没底。留 1.5 秒,是让人看清最后一项的状态,也是给"我是不是漏了什么"这个念头一个落点。

失败和取消的项不清。这条是硬规矩:只要队列里有一个失败或者被取消的项,整个队列原样保留,右键还能重试、能单独清除。全清掉看着干净,实际上把"哪条挂了"的证据也一起扫走了。清理是为了省事,不是为了遮问题。

真正麻烦的是竞态——这也是七亿批量远程管理工具里所有后台任务共有的问题。定时器是从"最后一项完成"那一刻开始算的,可这 1.5 秒里用户完全可能又拖进来一批文件。要是定时器到点不看状态直接清,新任务的队列会被上一轮的尾巴顺手带走。所以触发时先查一遍:只要队列里还有「等待」或者「进行中」的项,这一轮就不清,面板也不收,等下一次全部完成再重新计时。

这块代码在 FtpForm.cs 和 SftpForm.cs 两个窗口里各有一份,逻辑一样。FTP 和 SFTP 的传输实现不同,但队列模型是同一套,所以清理规则也照搬。倒是提醒了我一件事:这两个窗口里类似的"复制粘贴"已经不少了,哪天要改队列结构,得两边一起动,漏一个就是一半好用一半不好用。

写完这段,我想起之前 FTP 删除卡死那回(那把不可重入的锁)。同样是"操作成功了,界面却没回来",那次是 _opLock 重入死锁,这次是队列状态没人收尾。客户端这东西,功能跑通只是一半,剩下一半全在"做完之后界面该是什么样"。

顺带说一句,文件夹上传下载后来改成"一个任务"(这篇里写过),队列里就不会出现几百个小项刷屏,自动清理的判定也简单了不少——一个任务一个状态,不用再猜"这批到底算完没完"。

现在的行为是:全成功,1.5 秒后自己清;有失败,留着让你处理;中途来新任务,这一轮跳过。三条规则加起来没多少代码,但每一条都是被自己或者测试同事问出来的。要是你还没试过七亿批量远程管理工具的传输队列,可以先拖一个文件夹进去看看,清空和收起是连着的,别以为是界面卡了。

自嘲一句:为了省用户点一次「清除」,我盯着队列面板看了一下午,最后写出来的东西,用户大概率根本注意不到——注意不到就对了。