async/await自定义异步等待器Awaiter:异步等待窗口任务

内容将会持续更新,有错误的地方欢迎指正,谢谢!
 

async/await自定义异步等待器Awaiter:异步等待窗口任务
     
TechX 坚持将创新的科技带给世界!

拥有更好的学习体验 —— 不断努力,不断进步,不断探索
TechX —— 心探索、心进取!

助力快速掌握 等待器Awaiter的定义

为初学者节省宝贵的学习时间,避免困惑!


前言:

  在现代软件开发中,异步编程是非常常见的。异步操作可以在后台执行,不会阻塞主线程,从而提高应用程序的响应性能。在C#语言中,我们通常使用async/await模式来处理异步操作,使代码更加简洁易读。

  在Unity中,我们经常需要处理异步操作,例如加载资源、网络请求或处理用户输入等。C# 提供了 async/await 异步编程模型,使得异步操作更加简单和易读。本文将介绍如何使用自定义异步等待器,并通过示例代码演示在Unity中使用异步操作来进行窗口任务的等待。


TechX 教程效果:

在这里插入图片描述



一、自定义异步等待器Awaiter

1、什么是自定义异步等待器Awaiter?


自定义异步等待器是指我们自己定义的、用于处理异步操作的类或结构。它需要实现INotifyCompletion接口,以便在异步操作完成时通知等待器继续执行。

自定义异步等待器通常包含以下内容:

1、异步操作结果类型(Result Type): 在定义自定义异步等待器时,我们需要确定异步操作的结果类型。例如,在Unity中,异步加载资源可能返回 Texture2D、GameObject 或其他资源类型。

2、等待器状态属性: 通常我们会定义一个布尔类型的属性来表示异步操作是否已完成。这个属性会在异步操作完成时设置为 true,以便等待器知道何时继续执行。

3、异步操作结果存储: 我们需要定义一个字段或属性来存储异步操作的结果。这个字段或属性会在异步操作完成时进行赋值。

4、继续操作委托(Continuation Delegate): 继续操作委托是一个 Action 类型的委托,用于在异步操作完成时进行续约操作。当等待器的状态属性变为 true 时,继续操作委托会被调用,以便通知等待器可以继续执行。

5、异步等待器接口实现: 自定义异步等待器需要实现 INotifyCompletion 接口。该接口包含 GetAwaiter()、OnCompleted(Action continuation) 和 GetResult() 方法。

2、自定义异步等待器Awaiter的实现


为了更好地理解异步等待器的概念,我们首先来实现一个简单的自定义异步等待器

public class UniversalAwaiter<T> : INotifyCompletion
{
    private T result;
    private Action continuation;

    public bool IsCompleted { get; private set; }

    public UniversalAwaiter<T> GetAwaiter() => this;

    public void SetResult(T value)
    {
        result = value;
        IsCompleted = true;
        continuation?.Invoke();
    }

    public T GetResult()
    {
        return result;
    }

    public void OnCompleted(Action continuation)
    {
        this.continuation = continuation;
    }
}

在上述代码中,我们实现了 UniversalAwaiter 类,并在其中定义了一些属性和方法:

T result: 用于存储异步操作的结果。

Action continuation: 用于存储在异步操作完成时要执行的继续操作。

bool IsCompleted: 表示异步操作是否已完成。

接着我们实现了 INotifyCompletion 接口,其中包含 GetAwaiter()、OnCompleted(Action continuation) 和 GetResult() 方法。GetAwaiter() 方法返回当前等待器对象本身,OnCompleted(Action continuation) 方法用于指定在异步操作完成时要执行的续约操作,而 GetResult() 方法用于获取异步操作的结果。

3、使用自定义异步等待器Awaiter


现在我们已经实现了自定义异步等待器,让我们来看看如何在Unity中使用它们来处理异步操作。

public class CustomAwaiterOperate: MonoBehaviour
{
	// 示例:使用异步等待器处理异步操作
	async Task MyAsyncFunction()
	{
	    // 创建异步等待器
	    UniversalAwaiter<int> myAwater = new UniversalAwaiter<int>();
	
	    // 异步操作:加载资源、网络请求等
	    // 请注意:在实际使用中,你需要执行真正的异步操作,并在操作完成时调用 myAwater.SetResult(result) 来设置结果。
	
	    // 等待异步操作完成
	    int result = await myAwater;
	
	    // 现在你可以使用异步操作的结果
	    Debug.Log("异步操作结果:" + result);
	}
}




二、使用自定义异步等待器Awaiter实现窗口任务等待

1、实现可等待窗口任务


在Unity中,经常需要显示一个窗口,并等待用户点击按钮进行确认或取消。我们可以使用 WindowTask 来处理此类窗口任务。

public class WindowTask<T> : UniversalAwaiter<int> where T : IConfirmation
{
    private T window;

    public WindowTask(T window)
    {
        this.window = window;
        window.OnConfirmation += Window_OnConfirmation;
    }

    private void Window_OnConfirmation(int buttonIndex)
    {
        if (window != null)
            window.OnConfirmation -= Window_OnConfirmation;

        SetResult(buttonIndex);

        window = default(T);
    }
}

在上述代码中,我们创建了一个泛型类 WindowTask,它继承自 UniversalAwaiter。WindowTask 类的泛型参数 T 必须实现 IConfirmation 接口,用于表示窗口的确认操作。

在构造函数中,我们传入一个实现了 IConfirmation 接口的窗口对象,并订阅窗口的 OnConfirmation 事件。当窗口的确认事件触发时,Window_OnConfirmation 方法将被调用,将按钮索引作为结果进行设置。

2、异步可等地窗口的实现


对于等待窗口的实现,你需要确保窗口控件(例如对话框)实现了IConfirmation接口,这是一个自定义的接口,通常包含用于确认操作的方法和事件。

在窗口控件实现IConfirmation接口时,你需要在合适的时机触发OnConfirmation事件,并传递用户点击的按钮索引。例如,在用户点击确定或取消按钮时,触发相应的事件并传入相应的按钮索引,通知等待窗口任务操作已完成。

public interface IConfirmation
{
    event Action<int> OnConfirmation; // 确认事件,传递用户点击的按钮索引
}

	public struct WindowData
    {
        public string title;

        public string msg;
        
        public ButtonData[] buttons;

        public Data(string title = null, string msg = null, ButtonData[] btns = null)
        {
            this.title = title;

            this.msg = msg;

            this.buttons = btns;
        }
    }

    public struct ButtonData
    {
        public string text;
        public ButtonData(string text)
        {
            this.text = text;
        }
    }

	public class SampleConfirmationWindow : MonoBehaviour, IConfirmation
	{
		private SampleConfirmationWindow instance;
        public SampleConfirmationWindow Instance
        {
            get {
                if (instance == null)
                {
                    GameObject obj = FindObjectOfType<SampleConfirmationWindow>()?.gameObject;
                    if (obj == null)
                    {
                        obj = new GameObject("SampleConfirmationWindow");
                    }
                    instance = obj.GetComponent<SampleConfirmationWindow>();
                    if (instance == null)
                    {
                        instance = obj.AddComponent<SampleConfirmationWindow>();
                    }
                }
                return instance;
            }
        }
        
	    public event Action<int> OnConfirmation;
	
	    public RectTransform buttonPrefabs;
	
	    public Text titleText;
	
	    public Text topicText;
	
	    public Data WindowData { get; private set; }
	
	    private void Start()
	    {
	         buttonPrefabs.gameObject.SetActive(false);
        	 UpdateMsg(WindowData);
	    }
	
	    private void OnDestroy()
	    {
	        OnConfirmation = null;
	    }
	
	    private void UpdateMsg(Data data)
	    {
	        //允许没有按钮的情况
	        titleText.text = data.title;
	        topicText.text = data.msg;
	
	        if (data.buttons == null || data.buttons.Length == 0)
	            return;
	
	        for (int i = 0, len = data.buttons.Length; i < len; i++)
	        {
	            var btnData = data.buttons[i];
	
	            var uiBtn = GenButton(btnData);
	
	            var btnIndex = i;
	
	            uiBtn.OnClick.AddListener(() => { Confirmation(btnIndex); });
	        }
	    }
	
	    protected UIButton GenButton(ButtonData btnData)
	    {
	        var btnGO = Instantiate(buttonPrefabs.gameObject, buttonPrefabs.parent);
	        
	        btnGO.SetActive(true);
	        
	        var uiButton = btnGO.GetComponent<Button>();
	        
	        uiButton.GetComponentInChildren<Text>().text = btnData.text
	        
	        return uiButton;
	    }
	
	    private void Confirmation(int val)
	    {
	        OnConfirmation?.Invoke(val);
	
	       	HideWindow();
	    }
	
	    public async static Task<int> ShowWindowAsync(Data windowData)
	    {
	        var window = ShowWindow(windowData);
	
	        return await new WindowTask<SampleConfirmationWindow>(window);
	    }
	
	
	    public static SampleConfirmationWindow ShowWindow(Data windowData)
	    {
			var tipsPopup = SampleConfirmationWindow.Instance;
	
	        tipsPopup.WindowData = windowData;
	
	        return tipsPopup;
	    }
	    
	    public static void HideWindow()
	    {
			Destory(SampleConfirmationWindow.Instance);
	    }
	}

3、实现可等待窗口任务


现在我们已经实现了自定义异步等待器和窗口任务,让我们来看看如何在Unity中使用它们来处理异步操作和等待窗口确认。

async void ShowConfirmationWindow()
{
	//创建一个异步窗口,并等待确认
    var result = await SampleConfirmationWindow.ShowWindowAsync(
    new Data("提示", "确认返回首页吗?",new ButtonData[]
	    {
	         new ButtonData("确定"),
	         new ButtonData("取消"),
	     }));
     if(result ==0)
     {
   			//当点击了确定按钮时,执行...	
	 }
	 if(result ==1)
     {
   			//当点击了取消按钮时,执行...	
	 }
}

在这里插入图片描述




三、总结


总结来说,等待窗口的实现条件包括:

1、窗口控件实现IConfirmation接口,包含确认事件OnConfirmation和显示对话框的方法Show。

2、自定义异步等待器实现INotifyCompletion接口,处理异步操作的等待和结果传递。

3、等待窗口任务类继承自自定义异步等待器,并处理窗口确认事件。

4、使用async/await模式来等待等待窗口任务完成,并获取操作结果。



TechX —— 心探索、心进取!

每一次跌倒都是一次成长

每一次努力都是一次进步

END

感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。

如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。

在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐沐森的故事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值