英文:
How UniTaskVoid subscribe to an event?
问题
UniTask的文档建议避免使用"async void",而是使用UniTaskVoid。但我找不到订阅事件的解决方案。
async void subscription
public class WindowGamePause : WindowView
{
[SerializeField] private Button _restartGameButton;
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame);
}
private async void RestartGame()
{
await Close();
_gameManager.RestartGame();
}
}
async UniTaskVoid subscription??
public class WindowGamePause : WindowView
{
[SerializeField] private Button _restartGameButton;
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame); //怎么做?
_restartGameButton.onClick.AddListener(RestartGame().Forget); //不工作正常 - 方法在这一行触发
}
private async UniTaskVoid RestartGame()
{
await Close();
_gameManager.RestartGame();
}
}
[更新]
我找到了一些解决方案。它运行正常,但我做错了什么,因为Rider说:"可以消除闭包:方法有重载以避免创建闭包"。但我没有任何想法如何避免闭包。
public class WindowGamePause : WindowView
{
[SerializeField] private Button _restartGameButton;
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame);
}
private void RestartGame()
{
UniTask.Void( async () =>
{
await Close();
_gameManager.RestartGame();
});
}
}
英文:
UniTask's documentation recommends to avoid "async void" and use UniTaskVoid instead. But I cannot find solution to subscribe to events
async void subscription
public class WindowGamePause : WindowView
{
[SerializeField] private Button _restartGameButton;
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame);
}
private async void RestartGame()
{
await Close();
_gameManager.RestartGame();
}
}
async UniTaskVoid subscription??
public class WindowGamePause : WindowView
{
[SerializeField] private Button _restartGameButton;
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame); //What to do?
_restartGameButton.onClick.AddListener(RestartGame().Forget); //Doesn't work correctly - the method fires on the line
}
private async UniTaskVoid RestartGame()
{
await Close();
_gameManager.RestartGame();
}
}
[UPDATE]
I found some solution. It works fine but I do something wrong because Rider says: "Closure can be eliminated: method has overload to avoid closure creation". And I don't have any ideas to avoid closures.
public class WindowGamePause : WindowView
{
[SerializeField] private Button _restartGameButton;
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame);
}
private void RestartGame()
{
UniTask.Void( async () =>
{
await Close();
_gameManager.RestartGame();
});
}
}
答案1
得分: 1
你可以简单地添加一个中间的void,如下所示:
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame);
}
private void RestartGame()
{
RestartGame.Forget();
}
或者,你也可以使用lambda表达式来实现,但是这样你无法在需要时移除监听器:
_restartGameButton.onClick.AddListener(() => RestartGameAsync().Forget());
问题在于,为了调用 Forget
,你已经必须调用该方法并返回一个 UniTaskVoid
,这将立即执行。
英文:
You can always simply add an in-between void like
private void Awake()
{
_restartGameButton.onClick.AddListener(RestartGame);
}
private void RestartGame()
{
RestartGame.Forget();
}
private async UniTaskVoid RestartGameAsync()
{
await Close();
_gameManager.RestartGame();
}
This basically could also be done with a lambda (but then you can't remove the listener in case it is ever needed)
_restartGameButton.onClick.AddListener(() => RestartGameAsync().Forget());
The problem is that in order to call Forget
you already have to call the method and return a UniTaskVoid
which will be immediately running.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论