ue3dUnityUniTask取消处理/与Task对比

UnityUniTask取消处理/与Task对比

分类:
ue3d - UnityUniTask取消处理/与Task对比

本文将介绍Unity的UniTask取消流程。

如何取消异步方法

首先,看一下如何取消一个异步方法。

对于任务

在写UniTask之前,先总结一下Task,要取消任务,请将CancellationToken传递给异步方法,如下所示:

using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;

public class Example : MonoBehaviour
{
    [SerializeField] private Button _cancelButton;
    
    private async void Start()
    {
        // 生成CancellationTokenSource
        var cts = new CancellationTokenSource();

        _cancelButton.onClick.AddListener(() =>
        {
            cts.Cancel();
        });
        
        // 将 CancellationTokenSource.Token 传递给异步方法
        await ExampleAsync(cts.Token);
    }
    
    private async Task ExampleAsync(CancellationToken cancellationToken = default)
    {
        // 如果此时取消则抛出 OperationCanceledException 的方法
        cancellationToken.ThrowIfCancellationRequested();

        for (var i = 0; i < 5; i++) {
            // 您可以将 cancellationToken 传递给 Task 工厂方法
            await Task.Run(() => Thread.Sleep(1000), cancellationToken);
        }
    }
}

如果取消,会抛出异常,所以处理一下。

对于UniTask

在UniTask的情况下,取消处理基本上与Task相同。

using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;

public class Example : MonoBehaviour
{
    [SerializeField] private Button _cancelButton;
    
    private async void Start()
    {
        // 生成CancellationTokenSource
        var cts = new CancellationTokenSource();

        _cancelButton.onClick.AddListener(() =>
        {
            cts.Cancel();
        });
        
        // 将 CancellationTokenSource.Token 传递给异步方法
        await ExampleAsync(cts.Token));
    }
    
    private async UniTask ExampleAsync(CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        for (var i = 0; i < 5; i++) {
            await Task.Run(() => Thread.Sleep(1000), cancellationToken);
        }
    }
}

Unity的AsyncOperation系统

UniTask在Unity的AsyncOperation结构中实现了GetAwaiter(),但是CancellationToken 不能作为这些的参数传递。

它们具有下面定义的名为WithCancellation()的扩展方法,因此使用它来传递CancellationToken。

using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Example : MonoBehaviour
{
    [SerializeField] private Button _cancelButton;
    
    private async void Start()
    {
        // 生成CancellationTokenSource
        var cts = new CancellationTokenSource();

        _cancelButton.onClick.AddListener(() =>
        {
            cts.Cancel();
        });

        // 将 WithCancellation 传递给那些在 Unity 的 AsyncOperation 中定义的 Awaiter
        await UnityWebRequest.Get("http://www.i3dtt.com").SendWebRequest().WithCancellation(cts.Token);
    }
}

链接到GameObject生命周期的CancellationToken

使用UniTask,可以获得与GameObject的生命周期关联的CancellationToken。通过将其传递给异步方法,可以实现一个在GameObject被销毁后将被取消的过程。

using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class Example : MonoBehaviour
{    
    private async void Start()
    {        
        // 生成一个 CancellationToken,当 GameObject 被销毁时将被取消
        await ExampleAsync(this.GetCancellationTokenOnDestroy());
    }
    
    private async UniTask ExampleAsync(CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        for (var i = 0; i < 5; i++) {
            await Task.Run(() => Thread.Sleep(1000), cancellationToken);
        }
    }
}

如何处理取消

接下来,总结一下如何处理取消异步方法。

基本上是尝试捕捉

取消异步方法时OperationCanceledException会抛出异常,Task和UniTask基本上都是通过try-catch来处理这个异常的。

using System;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class Example : MonoBehaviour
{
    private async void Start()
    {
        try
        {
            await ExampleAsync(this.GetCancellationTokenOnDestroy());
        }
        catch (OperationCanceledException e)
        {
            // 捕获OperationCanceledException并处理取消
            Debug.Log("它被取消了");
            throw;
        }
    }
    
    private async UniTask ExampleAsync(CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        for (var i = 0; i < 5; i++) {
            await Task.Run(() => Thread.Sleep(1000), cancellationToken);
        }
    }
}

使用SuppressCancellationThrow获取取消状态作为返回值

在UniTask的情况下,可以使用以下方法UniTask.SuppressCancellationThrow()接收取消状态作为返回值。

using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class Example : MonoBehaviour
{
    private async void Start()
    {
        // SuppressCancellationThrow 返回取消状态作为返回值
        var canceled = await ExampleAsync(this.GetCancellationTokenOnDestroy()).SuppressCancellationThrow();
        if (canceled)
        {
            Debug.Log("它被取消了");
        }
    }
    
    private async UniTask ExampleAsync(CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();

        for (var i = 0; i < 5; i++) {
            await Task.Run(() => Thread.Sleep(1000), cancellationToken);
        }
    }
}

以上是关于UniTask的取消流程的全部内容,如果你有任何反馈,请随时在本页面下方留言。

相关信息

  • 类型:知识
  • 字数:367
  • 字符:5767
  • 适用软件:Unity
  • 说明:无
  • 编号:163833

热门内容

提示:3D天堂作为服务提供者,尊重网络版权及知识产权,对某些行为的发生不具备充分的监控能力,若无意间侵犯到您的权利,请 联系我们,我们会在收到信息后尽快给予处理。

本站文章版权归本站自创作者所有,未经允许不得转载!