内容将会持续更新,有错误的地方欢迎指正,谢谢!
拥有更好的学习体验 —— 不断努力,不断进步,不断探索 |
助力快速掌握 等待器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模式来等待等待窗口任务完成,并获取操作结果。
每一次跌倒都是一次成长 每一次努力都是一次进步 |
感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!