在Android下异步/等待不良做法?

时间:2014-03-24 14:51:50

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

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

我使用了很多async / await来处理文件IO,对话框,网络等...

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

  • 该应用程序稍后恢复,好像什么也没发生
  • 如果内存不足,应用会终止。

在这两种情况下,没有任何记事本泄漏,控制流程没有变化。

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

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

我的假设是真的吗?如果是的话,可以做些什么? (不使程序像async / await发明那样复杂)

2 个答案:

答案 0 :(得分:1)

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

如果您的活动中有CancellationTokenSource,那该怎么办?然后在OnPause中,您可以调用取消,然后使用:

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
  3. 在我自己的实践中,我发现了两个你可以违反这些一般规则的地方。

    1. 如果你在顶部' (例如,UI)您可能需要将代码声明为async void的地方,因为您重写的委托将void作为返回类型。一个典型的例子是使用button.Click方法。
    2. 我有一个数据库调用,它在数据库中查找单个值。如果我将其转换为异步,我的代码的很多将在其他地方进行更改。我发现,如果你有保证,我的意思是保证,那就是在'底部'你的代码,特别是你所调用的方法之下没有任何方法使用异步,那么你可以安全地调用任务上的.Result。这使我免于不必要地删除了一半代码。
    3. 希望这有帮助。

答案 1 :(得分:0)

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