Cancellation on DOTween works, but I don't catch an OperationCanceledException, nor do I get the correct value of canceled when I suppress it.
SherryOever18 opened this issue · 2 comments
SherryOever18 commented
Unity : 2022.3.13f1
UniTask : 2.5.3
DOTween : 1.2.765
Here is the code :
using DG.Tweening;
using Cysharp.Threading.Tasks;
using UnityEngine;
using System.Threading;
using UnityEngine.UI;
using System;
public class NewBehaviourScript : MonoBehaviour
{
[SerializeField]
RectTransform rectTransform;
[SerializeField]
Button button;
CancellationTokenSource moveCancellation;
void Start()
{
moveCancellation = new CancellationTokenSource();
button.onClick.AddListener(() => moveCancellation.Cancel());
Foo(moveCancellation.Token).Forget();
}
async UniTaskVoid Foo(CancellationToken cancellationToken)
{
try
{
await rectTransform.DOAnchorPos(1000f * Vector2.right, 10f).WithCancellation(cancellationToken);
}
catch (OperationCanceledException ex)
{
Debug.LogException(ex);
}
}
void OnDestroy()
{
moveCancellation.Dispose();
}
}
using DG.Tweening;
using Cysharp.Threading.Tasks;
using UnityEngine;
using System.Threading;
using UnityEngine.UI;
public class NewBehaviourScript : MonoBehaviour
{
[SerializeField]
RectTransform rectTransform;
[SerializeField]
Button button;
CancellationTokenSource moveCancellation;
void Start()
{
moveCancellation = new CancellationTokenSource();
button.onClick.AddListener(() => moveCancellation.Cancel());
Foo(moveCancellation.Token).Forget();
}
async UniTaskVoid Foo(CancellationToken cancellationToken)
{
bool canceled = await rectTransform.DOAnchorPos(1000f * Vector2.right, 10f).WithCancellation(cancellationToken).SuppressCancellationThrow();
Debug.Log(canceled);
}
void OnDestroy()
{
moveCancellation.Dispose();
}
}
Saismirk commented
I can confirm these tests fail. While the tasks are indeed cancelled, they neither throw a Cancellation exception nor return the proper bool value when the exception is suppressed.
const float TWEEN_TIME = 2f;
const int DEFAULT_WAIT_MS = 500;
bool _isCanceled;
[UnityTest]
public IEnumerator DoTweenTaskCanceledReturnValueTest() => UniTask.ToCoroutine(async () => {
var cts = new CancellationTokenSource();
DoTweenTask(cts.Token).Forget();
await UniTask.Delay(DEFAULT_WAIT_MS);
cts.Cancel();
await UniTask.Delay(DEFAULT_WAIT_MS);
Assert.That(_isCanceled, Is.True);
});
[UnityTest]
public IEnumerator DoTweenTaskTimeoutReturnValueTest() => UniTask.ToCoroutine(async () => {
using var timeoutController = new TimeoutController();
DoTweenTask(timeoutController.Timeout(DEFAULT_WAIT_MS)).Forget();
await UniTask.Delay(DEFAULT_WAIT_MS + 100);
Assert.That(_isCancelled, Is.True);
});
async UniTaskVoid DoTweenTask(CancellationToken token) {
_isCanceled = false;
var time = Time.time;
var value = 0;
_isCanceled = await DOTween.To(() => value, x => value = x, 100, TWEEN_TIME)
.WithCancellation(token)
.SuppressCancellationThrow();
time = Time.time - time;
Debug.Log(time < TWEEN_TIME
? $"{nameof(DoTweenTask)} is cancelled after {time} seconds"
: $"{nameof(DoTweenTask)} is completed after {time} seconds");
}
hadashiA commented
@SherryOever18
The behavior when a DOTween is canceled can be optionally adjusted.
By default, no exception is used, but the following will throw an OperationCancellationException
while killing the tween.
await rectTransform.DOAnchorPos(1000f * Vector2.right, 10f)
.ToUniTask(TweenCancelBehaviour.KillAndCancelAwait, cancellationToken);