从 WhenAll 取消所有任务

问题描述 投票:0回答:1

在下面的代码中,取消源令牌被传递给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 日,仅在我未使用的预发布包中)并且需要使用协程来解决问题,但也许我没有正确使用令牌和任务。

c# unit-testing unity-game-engine task cancellationtokensource
1个回答
0
投票

取消源令牌传递给 Task.WhenAll。

不,它被传递给

Task.Run
,所以如果令牌已经被取消,
Task.WhenAll(..)
将永远不会运行。如果令牌尚未取消,它可能不会产生任何影响。以这种方式使用
Task.Run
而不是仅仅等待
Task.WhenAll
似乎也很奇怪。

Task.WhenAll 没有任何需要取消令牌的重载,因此如果您想要正确取消,您可能需要确保将令牌传递给每个任务,并且每个任务实际上正确使用该令牌。

奇怪的情况是第一次运行没有通过,然后后面的运行通过。我怀疑以下运行实际上取消了上次运行中的一些剩余任务,并且未按预期工作。

一个可能的原因是某些对象在测试之间没有重新创建。如果您有多个测试,那么很容易无意中在测试之间创建依赖关系。但我不熟悉统一测试框架,所以我不能真正建议修复。

© www.soinside.com 2019 - 2024. All rights reserved.