Merge pull request #20418 from peppy/fix-leaderboard-crash

Fix intermittent leaderboard crash due to request finishing after drawable is disposed
This commit is contained in:
Dan Balasescu 2022-09-26 17:10:32 +09:00 committed by GitHub
commit 426ab176d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 9 deletions

View File

@ -185,10 +185,15 @@ namespace osu.Game.Online.Leaderboards
if (scores != null) if (scores != null)
this.scores.AddRange(scores); this.scores.AddRange(scores);
// Schedule needs to be non-delayed here for the weird logic in refetchScores to work. // Non-delayed schedule may potentially run inline (due to IsMainThread check passing) after leaderboard is disposed.
// If it is removed, the placeholder will be incorrectly updated to "no scores" rather than "retrieving". // This is guarded against in BeatmapLeaderboard via web request cancellation, but let's be extra safe.
// This whole flow should be refactored in the future. if (!IsDisposed)
Scheduler.Add(applyNewScores, false); {
// Schedule needs to be non-delayed here for the weird logic in refetchScores to work.
// If it is removed, the placeholder will be incorrectly updated to "no scores" rather than "retrieving".
// This whole flow should be refactored in the future.
Scheduler.Add(applyNewScores, false);
}
void applyNewScores() void applyNewScores()
{ {

View File

@ -89,6 +89,8 @@ namespace osu.Game.Screens.Select.Leaderboards
private IDisposable scoreSubscription; private IDisposable scoreSubscription;
private GetScoresRequest scoreRetrievalRequest;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
@ -151,14 +153,14 @@ namespace osu.Game.Screens.Select.Leaderboards
else if (filterMods) else if (filterMods)
requestMods = mods.Value; requestMods = mods.Value;
var req = new GetScoresRequest(fetchBeatmapInfo, fetchRuleset, Scope, requestMods); scoreRetrievalRequest = new GetScoresRequest(fetchBeatmapInfo, fetchRuleset, Scope, requestMods);
req.Success += r => SetScores( scoreRetrievalRequest.Success += response => SetScores(
scoreManager.OrderByTotalScore(r.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo))), scoreManager.OrderByTotalScore(response.Scores.Select(s => s.ToScoreInfo(rulesets, fetchBeatmapInfo))),
r.UserScore?.CreateScoreInfo(rulesets, fetchBeatmapInfo) response.UserScore?.CreateScoreInfo(rulesets, fetchBeatmapInfo)
); );
return req; return scoreRetrievalRequest;
} }
protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope) protected override LeaderboardScore CreateDrawableScore(ScoreInfo model, int index) => new LeaderboardScore(model, index, IsOnlineScope)
@ -218,7 +220,9 @@ namespace osu.Game.Screens.Select.Leaderboards
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);
scoreSubscription?.Dispose(); scoreSubscription?.Dispose();
scoreRetrievalRequest?.Cancel();
} }
} }
} }