修正音频异步取消语义

This commit is contained in:
JSD\13999
2026-05-20 11:05:33 +08:00
parent 05ecb0916c
commit e866e75e86
2 changed files with 54 additions and 0 deletions

View File

@@ -211,6 +211,10 @@ namespace FlowScope.Audio
var handle = await _resources.LoadAsync<AudioClip>(key, cancellationToken);
return ValidateLoadedClip(key, handle);
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to load audio clip '{key}'.", exception);

View File

@@ -209,6 +209,34 @@ namespace FlowScope.Tests.PlayMode.Audio
Assert.That(handle.IsPlaying, Is.True);
}
[UnityTest]
public System.Collections.IEnumerator PlayBgmAsync_WhenCanceled_ThrowsOperationCanceledException()
{
var service = CreateService();
using var cts = new CancellationTokenSource();
cts.Cancel();
var sourceCountBeforePlay = Object.FindObjectsOfType<AudioSource>().Length;
yield return ThrowsAsync<OperationCanceledException>(
service.PlayBgmAsync("bgm-a", cancellationToken: cts.Token));
Assert.That(Object.FindObjectsOfType<AudioSource>().Length, Is.EqualTo(sourceCountBeforePlay));
}
[UnityTest]
public System.Collections.IEnumerator PlaySfxAsync_WhenCanceled_ThrowsOperationCanceledException()
{
var service = CreateService();
using var cts = new CancellationTokenSource();
cts.Cancel();
var sourceCountBeforePlay = Object.FindObjectsOfType<AudioSource>().Length;
yield return ThrowsAsync<OperationCanceledException>(
service.PlaySfxAsync("sfx", cts.Token));
Assert.That(Object.FindObjectsOfType<AudioSource>().Length, Is.EqualTo(sourceCountBeforePlay));
}
private AudioService CreateService(AudioServiceConfig config = null)
{
var gameObject = new GameObject("AudioServiceTest");
@@ -249,6 +277,27 @@ namespace FlowScope.Tests.PlayMode.Audio
onCompleted(task.Result);
}
private static System.Collections.IEnumerator ThrowsAsync<TException>(Task task)
where TException : Exception
{
while (!task.IsCompleted)
{
yield return null;
}
if (task.IsFaulted && task.Exception?.GetBaseException() is TException)
{
yield break;
}
if (task.IsCanceled && typeof(TException) == typeof(OperationCanceledException))
{
yield break;
}
Assert.Fail($"Expected {typeof(TException).Name}.");
}
private static AudioClip CreateClip(string name, float lengthSeconds)
{
var sampleCount = Mathf.CeilToInt(44100 * lengthSeconds);
@@ -285,6 +334,7 @@ namespace FlowScope.Tests.PlayMode.Audio
where T : class
{
LoadRequests++;
cancellationToken.ThrowIfCancellationRequested();
if (typeof(T) != typeof(AudioClip))
{
throw new InvalidOperationException($"missing resource: {key}");