Fix various data races causing crashes or incorrect leaderboard states

This commit is contained in:
smoogipoo
2018-04-16 17:39:03 +09:00
parent f59eef072d
commit 1b9d54a6ad

View File

@ -39,8 +39,9 @@ namespace osu.Game.Screens.Select.Leaderboards
private readonly LoadingAnimation loading; private readonly LoadingAnimation loading;
private IEnumerable<Score> scores; private ScheduledDelegate showScoresDelegate;
private IEnumerable<Score> scores;
public IEnumerable<Score> Scores public IEnumerable<Score> Scores
{ {
get { return scores; } get { return scores; }
@ -59,29 +60,34 @@ namespace osu.Game.Screens.Select.Leaderboards
// ensure placeholder is hidden when displaying scores // ensure placeholder is hidden when displaying scores
PlaceholderState = PlaceholderState.Successful; PlaceholderState = PlaceholderState.Successful;
// schedule because we may not be loaded yet (LoadComponentAsync complains). var flow = scrollFlow = new FillFlowContainer<LeaderboardScore>
Schedule(() =>
{ {
LoadComponentAsync(new FillFlowContainer<LeaderboardScore> RelativeSizeAxes = Axes.X,
{ AutoSizeAxes = Axes.Y,
RelativeSizeAxes = Axes.X, Spacing = new Vector2(0f, 5f),
AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Top = 10, Bottom = 5 },
Spacing = new Vector2(0f, 5f), ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) })
Padding = new MarginPadding { Top = 10, Bottom = 5 }, };
ChildrenEnumerable = scores.Select((s, index) => new LeaderboardScore(s, index + 1) { Action = () => ScoreSelected?.Invoke(s) })
}, f =>
{
scrollContainer.Add(scrollFlow = f);
int i = 0; // schedule because we may not be loaded yet (LoadComponentAsync complains).
foreach (var s in f.Children) showScoresDelegate?.Cancel();
{ if (!IsLoaded)
using (s.BeginDelayedSequence(i++ * 50, true)) showScoresDelegate = Schedule(showScores);
s.Show(); else
} showScores();
scrollContainer.ScrollTo(0f, false); void showScores() => LoadComponentAsync(flow, _ =>
}); {
scrollContainer.Add(flow);
int i = 0;
foreach (var s in flow.Children)
{
using (s.BeginDelayedSequence(i++ * 50, true))
s.Show();
}
scrollContainer.ScrollTo(0f, false);
}); });
} }
} }
@ -249,26 +255,33 @@ namespace osu.Game.Screens.Select.Leaderboards
PlaceholderState = PlaceholderState.Retrieving; PlaceholderState = PlaceholderState.Retrieving;
loading.Show(); loading.Show();
var localBeatmap = Beatmap;
getScoresRequest = new GetScoresRequest(Beatmap, osuGame?.Ruleset.Value ?? Beatmap.Ruleset, Scope); getScoresRequest = new GetScoresRequest(Beatmap, osuGame?.Ruleset.Value ?? Beatmap.Ruleset, Scope);
getScoresRequest.Success += r => getScoresRequest.Success += r => Schedule(() =>
{ {
if (localBeatmap != Beatmap)
return;
Scores = r.Scores; Scores = r.Scores;
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores; PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
}; });
getScoresRequest.Failure += onUpdateFailed;
getScoresRequest.Failure += e => Schedule(() =>
{
if (localBeatmap != Beatmap)
return;
if (e is OperationCanceledException)
return;
PlaceholderState = PlaceholderState.NetworkFailure;
Logger.Error(e, @"Couldn't fetch beatmap scores!");
});
api.Queue(getScoresRequest); api.Queue(getScoresRequest);
} }
private void onUpdateFailed(Exception e)
{
if (e is OperationCanceledException)
return;
PlaceholderState = PlaceholderState.NetworkFailure;
Logger.Error(e, @"Couldn't fetch beatmap scores!");
}
private void replacePlaceholder(Placeholder placeholder) private void replacePlaceholder(Placeholder placeholder)
{ {
var existingPlaceholder = placeholderContainer.Children.LastOrDefault() as Placeholder; var existingPlaceholder = placeholderContainer.Children.LastOrDefault() as Placeholder;