C# Android下的异步/等待坏习惯?

C# Android下的异步/等待坏习惯?,c#,android,xamarin.android,xamarin,async-await,C#,Android,Xamarin.android,Xamarin,Async Await,目前,我正在将现有的C#Windows 8/iOS应用程序移植到Android(使用Xamarin) 我对文件IO、对话框、网络等使用了大量异步/等待功能 当应用程序在等待呼叫期间暂停/挂起时会发生什么情况? 在Windows和iOS下,有两种可能: 应用程序稍后会恢复,就好像什么都没发生一样 如果内存不足,应用程序将被终止 在这两种情况下,都没有内存泄漏,控制流也没有变化 然而,在Android下,活动可以在进程保持活动状态的同时被销毁和重新创建。在我对async/Wait的理解中,这意味

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

我对文件IO、对话框、网络等使用了大量异步/等待功能

当应用程序在等待呼叫期间暂停/挂起时会发生什么情况? 在Windows和iOS下,有两种可能:

  • 应用程序稍后会恢复,就好像什么都没发生一样
  • 如果内存不足,应用程序将被终止
在这两种情况下,都没有内存泄漏,控制流也没有变化

然而,在Android下,活动可以在进程保持活动状态的同时被销毁和重新创建。在我对async/Wait的理解中,这意味着:

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

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

Android活动保证在活动被停用/销毁之前调用OnPause,在启动时调用OnResume(请参阅)

如果您的活动中有一个CancellationTokenSource如何。然后在OnPause中,您可以调用Cancel,然后使用:

try
{
    // Your async code
    ...
}
catch (OperationCancelledException e)
{
}
有关取消异步任务的信息,请参见

与其说是一个明确的答案,不如说是一个建议,但我希望它能有所帮助

编辑:

当我开始在代码中引入async/await时,我发现它就像一个僵尸病毒。一旦你开始异步,你会发现它会蔓延到你代码的其他部分。这可能是因为同样的原因,您有很多异步调用。通常有两条规则需要遵循:

  • 将方法声明为
    public async Task Foo()
    而不是
    public async void Foo()
  • 在我自己的实践中,我发现了两个可以打破这些一般规则的地方

  • 如果您处于代码的“顶部”(即UI),则可能需要将代码声明为async void,因为您要重写的委托将void作为返回类型。一个典型的例子是使用按钮。单击方法
  • 我有一个数据库调用,它在数据库中查找单个值。如果我将其转换为异步,我在其他地方的许多代码将不得不更改。我发现,如果您保证(我的意思是保证)处于代码的“底部”,特别是在您调用的方法下面没有一个方法使用async,那么您可以安全地调用任务的.Result。这使我避免了不必要地异步一半代码

  • 希望这有帮助。

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

    似乎是一个合理的解决方案。但这意味着要做很多工作。我有140次“等待”和大约40个异步方法,其中必须包含try-catch块。我必须对每个异步方法都这样做,即使平均运行时间只有20毫秒左右。好的,我将等待其他建议。如果没有人,我会将你的建议标记为答案。使用服务:我的应用程序中有140次“等待”。大多数任务都不是长时间运行的任务,但只需要20毫秒左右。服务会使一切变得复杂。Fragment with RetainInstance:你能详细说明一下吗?不涉及网络的任务,大约20毫秒就可以运行了synchronously@Sarge博尔希:我正在将现有的Windows8应用程序移植到Android上。Windows 8要求文件读/写和对话框使用异步。我希望尽可能多地重用代码。所以我不想删除100个等待并更改所有助手方法。(我正在使用Xamarin,所以理论上我可以重用几乎所有东西。)这只是理论上的。。。很可能您不仅需要更改整个UI代码/标记,还需要更改一些真实的逻辑