如何使用回调在任何函数中调用异步等待方法

Posted

技术标签:

【中文标题】如何使用回调在任何函数中调用异步等待方法【英文标题】:How to call async-wait method in any function by using callback 【发布时间】:2022-01-19 13:38:00 【问题描述】:

我在 Unity 2020.3 中使用 UniTask。 我想调用一个异步方法,它在 Unity 事件函数中返回一个 UniTask。

由于某种原因,我无法将事件函数更改为异步版本,有没有其他方法可以调用它?

比如,把异步方法包装成回调函数?


例如,我有一个这样的异步函数:

public void async UniTask<string> GetStringAsync();

我想这样称呼它:

public class MyMonoBehaviour: MonoBehaviour

   pirvate string myString;


   pirvate void Start()
   
       myString = await GetStringAsync();
   

我不能在 Start() 中使用 await,因为它不是异步函数。 所以,我想把GetStringAsync()包装成一个回调函数并在Start()中调用它,但是我不知道该怎么做。

我知道最简单的解决方案是将Start()更改为async Start()

但是如果我想在任何普通函数中调用GetStringAsync() 怎么办?再次将其更改为异步? 我不喜欢 async 在我的代码中像病毒一样传播。因为函数可能是一些遗留代码,所以想尽量少修改。

【问题讨论】:

您能否展示您的代码并进一步解释您到底想要做什么以及您尝试了什么? @derHugo 感谢您的回复,我已更新问题并添加更多详细信息。 I cannot use await in Start() because it is not an async function .. 你试过把它变成async吗? ^^ @derHugo 是的,让它异步是最简单的解决方案,我只是想知道是否可以将异步函数包装到回调中。 我不完全理解你的意思,但是 Unity 允许将 Start 设为异步方法 【参考方案1】:

我会通过将签名更改为async void Start() 来解决这个问题。这样可行。如果您需要将 Update 延迟到 Start 完成,请将 Start 更改为协程并使用 UniTask 的 API 从任务创建迭代器(您将产生)。

注意:我不使用UniTask 库,但它似乎与Async Await Utils 相当。两者都为常见的 Unity 类型提供了GetAwaiter() 扩展方法。当然有一些函数可以让协程等待任务(通过将其包装在 IEnumerator 中)。

【讨论】:

嗨@piojo,如果我无法将 Start() 更改为异步版本,有什么解决方案吗? @Yongyi 我没有发现无法将Start()签名更改为async的情况,即使使用继承或接口也是如此。但是如果你不能,你可以通过创建一个async void 辅助方法并从Start() 调用它来完成此操作。 async void StartAsync() await GetStringAsync(); void Start() StartAsync(); 【参考方案2】:

我找到了自己想要的解决方案。

我创建了两个包装函数,如下所示:

public void GetString(Action<string> onDone) 
    AsyncToCallbackAsync(onDone).Forget();


private async UniTask AsyncToCallbackAsync(Action<string> onDone) 
    string s = await GetStringAsync();
    onDone(s);

而且我可以使用回调在任何普通函数中调用GetString()。 也许我没有把我的问题描述清楚,但这就是我想要的结果。

【讨论】:

【参考方案3】:

如this article 中所述,“标记为async void 的方法表示某些异步行为的根级别‘入口点’。考虑它们的一个好方法是它们是‘即发即弃’的任务关闭并在后台执行一些事情,而任何调用代码都会立即继续。” 因此,您可以创建自己的“根”async void 方法并直接从 void Start 调用它。例如:

void Start()

    Load();


async void Load()

    myString = await GetStringAsync();

【讨论】:

以上是关于如何使用回调在任何函数中调用异步等待方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从同步方法调用中回调而不等待它?

如何让 Lambda 函数等待异步操作完成?

java中5种异步转同步方法

如何将节点中的异步回调添加到函数调用?

如何等待异步方法的回调返回值?

如何等待异步方法的回调返回值?