Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xamarin 处理异步方法的配置更改_Xamarin_Xamarin.android_Async Await_C# 5.0 - Fatal编程技术网

Xamarin 处理异步方法的配置更改

Xamarin 处理异步方法的配置更改,xamarin,xamarin.android,async-await,c#-5.0,Xamarin,Xamarin.android,Async Await,C# 5.0,我有一个活动,其中包含一个异步方法。此异步方法正在长时间运行。异步方法返回后,需要更新UI,并且一些控件引用活动。 目前,如果在异步任务运行时未进行配置更改(如屏幕旋转),则一切正常。但是,如果在运行时发生配置更改,则会引发异常活动并不会更新UI。从我阅读的内容来看,这似乎是因为异步方法捕获上下文,然后尝试更新旧上下文,而旧上下文在配置更改后当然会被破坏 我的问题是:解决这个问题的最好方法是什么,或者在最坏的情况下解决它?我个人认为你只有三个选择 您可以永久或临时禁用旋转,但这是一种不好的做法

我有一个活动,其中包含一个异步方法。此异步方法正在长时间运行。异步方法返回后,需要更新UI,并且一些控件引用活动。 目前,如果在异步任务运行时未进行配置更改(如屏幕旋转),则一切正常。但是,如果在运行时发生配置更改,则会引发异常活动并不会更新UI。从我阅读的内容来看,这似乎是因为异步方法捕获上下文,然后尝试更新旧上下文,而旧上下文在配置更改后当然会被破坏


我的问题是:解决这个问题的最好方法是什么,或者在最坏的情况下解决它?

我个人认为你只有三个选择

  • 您可以永久或临时禁用旋转,但这是一种不好的做法
永久禁用它设置配置更改

[Activity(Label = "...", ConfigurationChanges = Android.Content.PM.ConfigChanges.KeyboardHidden | Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]   
要在任务工作时临时禁用它,应禁用旋转处理

禁用

使能

  • 如果您使用的是fragment,则可以使用
    RetainInstance=true
    防止碎片销毁。这可能有效,但我从未测试过

  • 您可以使用
    CancelationToken
    取消任务,然后在
    OnRestoreInstanceState()
    下面是如何取消任务的示例

    
    {
    取消源cts;
    ...
    //如果下载过程已在进行中,请取消它。
    如果(cts!=null)
    {
    cts.Cancel();
    }
    //现在,如果再次选择按钮,则设置cts以取消当前进程。 CancellationTokenSource newCTS=新的CancellationTokenSource(); cts=新cts;
    尝试 { //如果有取消请求,则发送cts.Token以承载消息。 等待访问WebAsync(cts.Token); } //单独捕获取消。 捕获(操作取消异常) { ResultsTextBox.Text+=“\r\n已取消下载。\r\n”; } 捕获(例外) { ResultsTextBox.Text+=“\r\n下载失败。\r\n”; } //当流程完成时,发出另一流程可以继续的信号。 if(cts==newCTS) cts=null; }

在任务中

async Task AccessTheWebAsync(CancellationToken ct)
{
    ...
    // Retrieve the website contents from the HttpResponseMessage.
    byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

    // Check for cancellations before displaying information about the 
    // latest site. 
    ct.ThrowIfCancellationRequested();
    ...
}

你可以做很多事情,但请不要去禁用手机的屏幕切换功能——这只会忽略你的用户

在高水平上,你必须做两件事:

  • 确保异步任务保持运行,并且在活动终止时不会重新启动
  • 您可以通过将任务移动到应用程序类中或(cleaner)移动到setRetainInstance设置为true的无头片段中来解决这个问题

  • 在活动中的onDestroy方法中,将其从异步任务中删除,在onCreate任务中,将活动交给异步任务(如果存在)

  • 这就是阻止异步任务调用旧上下文的原因,可以使用异步任务上的简单java setter来完成。如果活动当前未连接,请不要忘记在任务中缓存结果。

    最后,我将异步任务封装在另一个类中,该类包含对当前活动的引用,该类实现了一个接口,该接口定义了一个处理异步响应和更新UI的方法


    该活动包含封装异步任务的静态变量,如果它在配置更改期间运行,则封装异步任务对该活动的引用将更新为新活动。

    感谢您的建议。我同意禁用旋转是非常糟糕的,我不会这么做。异步任务在轮换时不会停止,所以这不是问题。看起来带保留状态的片段是最干净的解决方案。谢谢你的建议。同意禁用旋转是个糟糕的主意,所以我不会这么做。似乎带有保留状态的片段是最干净的解决方案。我没有考虑过取消该任务,但这也可以工作,但这意味着该任务可能需要重新启动。考虑到我们是C#举办一些活动也可能奏效,但这似乎很混乱。我会将此作为答案,因为它提供了最多的建议和示例。
    this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Sensor;
    
    async Task AccessTheWebAsync(CancellationToken ct)
    {
        ...
        // Retrieve the website contents from the HttpResponseMessage.
        byte[] urlContents = await response.Content.ReadAsByteArrayAsync();
    
        // Check for cancellations before displaying information about the 
        // latest site. 
        ct.ThrowIfCancellationRequested();
        ...
    }