Skip to content

Commit

Permalink
Replace all usages of Task.Result with extension method with added …
Browse files Browse the repository at this point in the history
…safety
  • Loading branch information
peppy committed Jan 3, 2022
1 parent 322e5c9 commit 78c657d
Show file tree
Hide file tree
Showing 9 changed files with 33 additions and 10 deletions.
1 change: 1 addition & 0 deletions CodeAnalysis/BannedSymbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ T:System.IComparable;Don't use non-generic IComparable. Use generic version inst
M:System.Enum.HasFlag(System.Enum);Use osu.Framework.Extensions.EnumExtensions.HasFlagFast<T>() instead.
F:System.UriKind.RelativeOrAbsolute;Incompatible results when run on mono (see https://www.mono-project.com/docs/faq/known-issues/urikind-relativeorabsolute/). Use Validation.TryParseUri(string, out Uri?) instead.
M:System.Threading.Tasks.Task.Wait();Don't use Task.Wait. Use Task.WaitSafely() to ensure we avoid deadlocks.
P:System.Threading.Tasks.Task`1.Result;Don't use Task.Result. Use Task.WaitSafelyForResult() to ensure we avoid deadlocks.
3 changes: 2 additions & 1 deletion osu.Framework.Tests/Visual/Sprites/TestSceneScreenshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
Expand Down Expand Up @@ -55,7 +56,7 @@ private void takeScreenshot()

host.TakeScreenshotAsync().ContinueWith(t => Schedule(() =>
{
var image = t.Result;
var image = t.WaitSafelyForResult();

var tex = new Texture(image.Width, image.Height);
tex.SetData(new TextureUpload(image));
Expand Down
2 changes: 1 addition & 1 deletion osu.Framework/Audio/Track/TrackBass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public override bool Looping
}
}

public override bool Seek(double seek) => SeekAsync(seek).Result;
public override bool Seek(double seek) => SeekAsync(seek).WaitSafelyForResult();

public async Task<bool> SeekAsync(double seek)
{
Expand Down
5 changes: 3 additions & 2 deletions osu.Framework/Audio/Track/Waveform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using ManagedBass;
using osu.Framework.Utils;
using osu.Framework.Audio.Callbacks;
using osu.Framework.Extensions;

namespace osu.Framework.Audio.Track
{
Expand Down Expand Up @@ -262,7 +263,7 @@ public async Task<Waveform> GenerateResampledAsync(int pointCount, CancellationT
/// <summary>
/// Gets all the points represented by this <see cref="Waveform"/>.
/// </summary>
public List<Point> GetPoints() => GetPointsAsync().Result;
public List<Point> GetPoints() => GetPointsAsync().WaitSafelyForResult();

/// <summary>
/// Gets all the points represented by this <see cref="Waveform"/>.
Expand All @@ -280,7 +281,7 @@ public async Task<List<Point>> GetPointsAsync()
/// <summary>
/// Gets the number of channels represented by each <see cref="Point"/>.
/// </summary>
public int GetChannels() => GetChannelsAsync().Result;
public int GetChannels() => GetChannelsAsync().WaitSafelyForResult();

/// <summary>
/// Gets the number of channels represented by each <see cref="Point"/>.
Expand Down
16 changes: 16 additions & 0 deletions osu.Framework/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,29 @@ namespace osu.Framework.Extensions
{
public static class TaskExtensions
{
/// <summary>
/// Safe alternative to Task.Wait which ensures the calling thread is not a thread pool thread.
/// </summary>
public static void WaitSafely(this Task task)
{
if (Thread.CurrentThread.IsThreadPoolThread)
throw new InvalidOperationException($"Can't use {nameof(WaitSafely)} from inside an async operation.");

#pragma warning disable RS0030
task.Wait();
#pragma warning restore RS0030
}

/// <summary>
/// Safe alternative to Task.Result which ensures the calling thread is not a thread pool thread.
/// </summary>
public static T WaitSafelyForResult<T>(this Task<T> task)
{
if (Thread.CurrentThread.IsThreadPoolThread)
throw new InvalidOperationException($"Can't use {nameof(WaitSafelyForResult)} from inside an async operation.");

#pragma warning disable RS0030
return task.Result;
#pragma warning restore RS0030
}
}
Expand Down
7 changes: 4 additions & 3 deletions osu.Framework/Graphics/Audio/WaveformGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Audio.Track;
using osu.Framework.Extensions;
using osu.Framework.Graphics.Batches;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.OpenGL.Vertices;
Expand Down Expand Up @@ -198,8 +199,8 @@ private void generate()

Waveform.GenerateResampledAsync((int)Math.Max(0, Math.Ceiling(DrawWidth * Scale.X) * Resolution), token).ContinueWith(w =>
{
var points = w.Result.GetPoints();
int channels = w.Result.GetChannels();
var points = w.WaitSafelyForResult().GetPoints();
int channels = w.WaitSafelyForResult().GetChannels();
double maxHighIntensity = points.Count > 0 ? points.Max(p => p.HighIntensity) : 0;
double maxMidIntensity = points.Count > 0 ? points.Max(p => p.MidIntensity) : 0;
double maxLowIntensity = points.Count > 0 ? points.Max(p => p.LowIntensity) : 0;
Expand All @@ -212,7 +213,7 @@ private void generate()
resampledMaxMidIntensity = maxMidIntensity;
resampledMaxLowIntensity = maxLowIntensity;

OnWaveformRegenerated(w.Result);
OnWaveformRegenerated(w.WaitSafelyForResult());

Invalidate(Invalidation.DrawNode);
});
Expand Down
3 changes: 2 additions & 1 deletion osu.Framework/IO/Stores/GlyphStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using osu.Framework.Extensions;
using osu.Framework.Graphics.Textures;
using osu.Framework.Logging;
using osu.Framework.Text;
Expand All @@ -34,7 +35,7 @@ public class GlyphStore : IResourceStore<TextureUpload>, IGlyphStore
protected readonly ResourceStore<byte[]> Store;

[CanBeNull]
protected BitmapFont Font => completionSource.Task.Result;
protected BitmapFont Font => completionSource.Task.WaitSafelyForResult();

private readonly TaskCompletionSource<BitmapFont> completionSource = new TaskCompletionSource<BitmapFont>();

Expand Down
3 changes: 2 additions & 1 deletion osu.Framework/Input/Handlers/Midi/MidiHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq;
using System.Threading.Tasks;
using Commons.Music.Midi;
using osu.Framework.Extensions;
using osu.Framework.Input.StateChanges;
using osu.Framework.Logging;
using osu.Framework.Platform;
Expand Down Expand Up @@ -87,7 +88,7 @@ private bool refreshDevices()
{
if (openedDevices.All(x => x.Key != input.Id))
{
var newInput = MidiAccessManager.Default.OpenInputAsync(input.Id).Result;
var newInput = MidiAccessManager.Default.OpenInputAsync(input.Id).WaitSafelyForResult();
newInput.MessageReceived += onMidiMessageReceived;
openedDevices[input.Id] = newInput;

Expand Down
3 changes: 2 additions & 1 deletion osu.Framework/Platform/TcpIpcProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using osu.Framework.Extensions;
using osu.Framework.Logging;

#nullable enable
Expand Down Expand Up @@ -101,7 +102,7 @@ private void listen(TcpListener listener)
{
try
{
var message = receive(stream, token).Result;
var message = receive(stream, token).WaitSafelyForResult();

if (message == null)
continue;
Expand Down

0 comments on commit 78c657d

Please sign in to comment.