在下面的代码中,取消源令牌被传递给Task.WhenAll。
try
{
InitializationResult[] rs = await Task.Run(() => Task.WhenAll(tasks), m_source.Token);
}
catch (OperationCanceledException e)
{
Debug.Log($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
return null;
}
finally
{
m_source?.Dispose();
}
使用 Unity 单元测试框架,其中任务只是等待 0.5 秒的两个类:
[UnityTest]
public IEnumerator InitializerTestCancelPasses()
{
var init = new InitializerProces();
Task<List<InitializationResult>> asyncOperation = init.Init(m_initializer);
while (!asyncOperation.IsCompleted)
{
init.Cancel();
yield return null;
}
Assert.IsNull(asyncOperation.Result);
}
奇怪的情况是第一次运行没有通过,然后后面的运行通过。我怀疑以下运行实际上取消了上次运行中的一些剩余任务,并且未按预期工作。
Unity 单元测试框架可能存在问题,因为尚未完全支持异步(截至 2024 年 10 月 4 日,仅在我未使用的预发布包中)并且需要使用协程来解决问题,但也许我没有正确使用令牌和任务。
取消源令牌传递给 Task.WhenAll。
不,它被传递给
Task.Run
,所以如果令牌已经被取消,Task.WhenAll(..)
将永远不会运行。如果令牌尚未取消,它可能不会产生任何影响。以这种方式使用Task.Run
而不是仅仅等待Task.WhenAll
似乎也很奇怪。
Task.WhenAll 没有任何需要取消令牌的重载,因此如果您想要正确取消,您可能需要确保将令牌传递给每个任务,并且每个任务实际上正确使用该令牌。
奇怪的情况是第一次运行没有通过,然后后面的运行通过。我怀疑以下运行实际上取消了上次运行中的一些剩余任务,并且未按预期工作。
一个可能的原因是某些对象在测试之间没有重新创建。如果您有多个测试,那么很容易无意中在测试之间创建依赖关系。但我不熟悉统一测试框架,所以我不能真正建议修复。