Scighost / Starward

Game Launcher for miHoYo - 米家游戏启动器
https://starward.scighost.com
MIT License
3.46k stars 165 forks source link

[Bug] 暂停后再继续引发`System.ArgumentNullException`异常 #1096

Open iamscottxu opened 1 week ago

iamscottxu commented 1 week ago

Checklist

Description

疑似 #1019 合入的代码导致。@Eric-Joker 想询问下这样写的原因是否和我理解的一样,讨论下看看有什么修复方案。 暂停继续逻辑问题,以下代码,依照我的理解,实际上是想解决暂停后马上继续会造成上一次任务未结束,下一次任务就开始了的问题。不过没有修改完整,导致启动任务时未设置TaskItems变量的值,导致空引用异常。 InstallGameStateModel.cs:

private void ContinueOrPause()
    {
        if (ButtonGlyph is PlayGlyph)
        {
            Task.Run(() =>
            {
                Task.WhenAll(Service.TaskItems).Wait(); //System.ArgumentNullException: Value cannot be null. (Parameter 'tasks')
                Service.Continue();
                InstallStarted?.Invoke(this, EventArgs.Empty);
            });
        }
        else if (ButtonGlyph is PauseGlyph)
        {
            Service.Pause();
        }
    }

此问题我建议弃用这种方案,因为这个问题涉及到取消时可能需要清理资源需要一定的时间,这个问题不仅在暂停时存在,取消下载和关闭程序时同样存在,上述方案虽然从使用者体验上来说,暂停速度很快,但是无法解决取消后立即重新开始下载时上一个下载任务可能还在清理资源的问题,也无法解决资源未清理完成程序就已经退出的问题。根据大部分软件的通行做法,应该添加”正在暂停/正在取消“的状态来修复更为妥当。 因为流式下载使用了更多的线程,且有更多的资源清理操作,暂停时间变长,快速“暂停/继续”和“取消/重新下载”大概率导致任务重复运行,出现行为异常,”正在暂停/正在取消“状态已经在 #1037 实现,并且 #1037 中已经提交代码修复上述问题,如果需要我可以单独提一个pr。

Reproduction Steps

  1. 打开程序,点击下载游戏;
  2. 点击暂停按钮暂停下载;
  3. 点击继续按钮恢复下载;
  4. 引发空引用异常。

Expected Behavior

点击继续按钮后不引发异常,继续完成未完成的下载任务。

Screenshots

image

Starward Version

main分支:93c028d

Windows Version

复现时系统版本:26100.1742(与操作系统版本无关)

Log

System.ArgumentNullException: Value cannot be null. (Parameter 'tasks')
   at System.Threading.Tasks.Task.WhenAll(IEnumerable`1 tasks)
   at Starward.Services.Download.InstallGameStateModel.<ContinueOrPause>b__42_0() in InstallGameStateModel.cs:line 112
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)

Additional Context

No response

Eric-Joker commented 1 week ago

异常是因为合并#1019删除了为TaskItems赋值的代码导致的。

目前还未实现流式解压所以我那简单的处理足以应付,因为释放资源的时长很短。将来实现后必然需要更好的处理方案。

修复方案择一,需要来个人 @Scighost 拍板():