在匿名异步函数中包装事件分配是否有意义?
让我们说这段代码在某些适配器类中:
beta
下面的代码在其他设置操作的类中:
示例1:
public event Action<int> someAction;
在这种情况下,HandleAction具有异步Task返回类型。
示例2:
_someAdapter.someAction += async (someParameter) =>
{
await HandleAction(someParamter);
};
在这种情况下,HandleAction具有异步void返回类型。
相同的问题也适用于按钮单击事件处理程序等。我已经看到了两者的示例,并且想知道为什么有时会把它包装起来。根据我的测试,似乎没有什么区别。
答案 0 :(得分:1)
我相信,使用匿名处理程序包装器,您将能够让C#垃圾收集器“解钩”并在即将被销毁的this
(在示例1)上销毁该处理程序。 / p>
this
之外的事件处理程序(在您的示例中不是这种情况)将受到特别注意,并且包装它是一个不错的选择。
如果this
可以生存很长时间,并且您有可能不得不再次you should use another strategy to avoid memory leak挂起该事件,就像讨论的on this question
返回类型差异are related to exception handling和it's ok to use an async void
on top-level methods and async event handlers。
希望对您有帮助。
答案 1 :(得分:1)
在您的示例中,可能没有明显的区别。这更多地与编码标准和最佳实践有关。通常,如果可以避免,建议您不要创建“异步无效”功能。该功能的目的是允许在无法更改其签名的函数中使用异步代码(例如覆盖)。 “异步无效”功能具有吞咽异常和难以组合的缺点。
例如,如果您想从另一个位置/方法调用HandleAction(通常这是使用命名方法而不是匿名函数的原因),除非它返回Task,否则将无法等待。
此外,如果HandleAction引发了异常,则无法等待它就无法捕获它,因此最好确保它会在内部处理所有异常。
答案 2 :(得分:0)
我无法评论您的适配器处理程序,但是...看到您说“相同的问题适用于...”时,答案可能与按钮单击事件处理程序的答案相同,等等,这是(可以说是UI应用程序中异步的最大好处)-您可以在UI线程之外的处理程序中执行昂贵的异步操作。
例如
_button.Click += async (...) =>
{
int answer = await ExpensiveHttpResultThatTakes10Seconds();
_answer.Text = answer.ToString();
};
如果不是 异步,则UI将冻结10秒钟,不响应单击,按键等。
由于它是异步的,因此UI在这10秒钟内保持响应,因为等待是无阻塞,正在处理UI事件甚至其他事件处理程序。
答案 3 :(得分:0)
我不建议使用匿名委托作为事件处理程序。原因是它可能涉及循环引用,因此垃圾收集器将无法释放内存-所谓的内存泄漏。
特别是在Xamarin世界中,托管垃圾收集器通常不知道对象的实际大小,因此开发人员应关注内存并分配其应用程序需求。
通过避免匿名委托,您可以通过删除事件处理程序分配来简化周期。