【问题标题】:async/await bad practice under Android?Android 下的 async/await 不好的做法?
【发布时间】:2014-05-02 00:12:40
【问题描述】:

目前我正在将现有的 C# Windows 8 / iOS 应用程序移植到 Android(使用 Xamarin)。

我在文件 IO、对话框、网络等方面使用了很多 async/await……

在等待调用期间应用暂停/暂停时会发生什么? 在 Windows 和 iOS 下有两种可能:

  • 应用程序稍后恢复,好像什么都没发生过一样
  • 如果内存不足,应用程序将终止。

在这两种情况下,都没有内存泄漏,控制流没有变化。

但是,在 Android 下,可以在进程保持活动状态时销毁并重新创建 Activity。在我对 async/await 的理解中,这意味着:

  • 未关闭的对话框将永远等待,这意味着可从调用者访问的对象(“t​​his”、局部变量等)将永远留在内存中(内存泄漏)
  • 当等待的网络请求完成而前一个 Activity 已被 Android 销毁时,“等待”之后的代码(例如文件写入)可能会发生冲突,因为存在 Activity 的两个正在运行的实例。

我的假设是真的吗?如果是,可以做什么? (没有让程序像以前发明 async/await 那样复杂)

【问题讨论】:

  • 不处理网络的,20ms左右的任务,同步运行即可
  • @Sarge Borsch:我正在将现有的 Windows 8 应用程序移植到 Android。 Windows 8 需要异步文件读/写和对话框。我想尽可能多地重用代码。所以我不想删除 100 个等待并更改所有辅助方法。 (我使用的是 Xamarin,所以理论上我几乎可以重用所有内容。)
  • 这只是理论上的......您可能不仅要更改整个 UI 代码/标记,还要更改一些实际逻辑

标签: c# android xamarin.android xamarin async-await


【解决方案1】:

Android Activity 保证在 Activity 被停用/销毁之前调用 OnPause,并在启动时调用 OnResume(请参阅http://developer.android.com/training/basics/activity-lifecycle/index.html)。

如果您的 Activity 中有可用的 CancellationTokenSource 怎么样。然后在 OnPause 中你可以调用 Cancel 然后使用:

try
{
    // Your async code
    ...
}
catch (OperationCancelledException e)
{
}

有关取消异步任务的信息,另请参阅 http://msdn.microsoft.com/en-us/library/jj155759.aspx。

更多的是建议而不是明确的答案,但我希望它会有所帮助。

编辑:

当我开始在我的代码中引入 async/await 时,我发现它就像一个僵尸病毒。一旦你开始异步,你会发现它遍布你的代码的其余部分。出于同样的原因,您可能有很多异步调用。一般有两条规则:

  1. 将方法声明为public async Task Foo() 而不是public async void Foo()
  2. Don't block on async code

在我自己的实践中,我发现了两个可以打破这些一般规则的地方。

  1. 如果您位于代码的“顶部”(即 UI),可能在某些地方您必须将代码声明为 async void,因为您要覆盖的委托将 void 作为返回类型。一个典型的例子是 button.Click 方法。
  2. 我有一个数据库调用,它在数据库中查找单个值。如果我将其转换为异步,我在其他地方的 lots 代码将不得不更改。我发现,如果您有保证(我的意思是保证)处于代码的“底部”,特别是您调用的方法下面的方法都没有使用异步,那么您可以安全地在任务上调用 .Result。这使我免于不必要地异步一半代码。

希望这会有所帮助。

【讨论】:

  • 似乎是一个合理的解决方案。但这意味着很多工作。我有 140 次“等待”和大约 40 个异步方法,我必须在其中包含 try-catch 块。我必须对每个异步方法都这样做,即使平均运行时间只有 20 毫秒左右。好的,我会等待其他建议。如果没有,我会将您的建议标记为答案。
【解决方案2】:

您可以使用服务来执行这些长时间运行的任务。另一种选择是使用无头片段(没有视图且将.RetainInstance 属性设置为true)。

【讨论】:

  • 使用服务:我的应用中有 140 次“等待”。其中大多数不是长时间运行的任务,但只需要 20 毫秒左右。服务会让一切变得复杂。带有 RetainInstance 的片段:您能详细说明一下吗?
猜你喜欢
  • 2014-03-13
  • 1970-01-01
  • 2015-11-16
  • 2020-03-25
  • 2019-10-08
  • 2016-06-02
  • 1970-01-01
  • 2022-06-12
  • 2015-04-10
相关资源
最近更新 更多