在 activity 上调用 'Finish()' 时出现 Xamarin NullReferenceException

Xamarin NullReferenceException when calling 'Finish()' on activity

我创建了一个启动 activity 并为结果注册到静态 EventHandler 的回调的生物识别身份验证服务。

处理人:

public class BiometricHandler : IBiometricHandler
{
    private TaskCompletionSource<byte[]> taskCompletionSource;

    public Task<byte[]> StartBiometricAuth()
    {
        Intent intent = new Intent(Android.App.Application.Context, typeof(BiometricActivity));
        intent.AddFlags(ActivityFlags.NewTask);
        Android.App.Application.Context.StartActivity(intent);

        taskCompletionSource = new TaskCompletionSource<byte[]>();
        BiometricActivity.BiometricEventHandler += BiometricCompleted;

        return taskCompletionSource.Task;
    }

    private void BiometricCompleted(object sender, BiometricEventArgs e)
    {
        taskCompletionSource.SetResult(e.Success ? e.Payload : new byte[] { });

        BiometricActivity.BiometricEventHandler -= BiometricCompleted;
    }
}

和 activity(显然不是实际代码):

public class BiometricActivity : Activity
{
    public static event EventHandler<BiometricEventArgs> BiometricEventHandler;
    private readonly int BIOMETRIC_REQUEST = 1;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        Intent intent = new Intent(Application.Context, typeof(BiometricAuth));
        StartActivityForResult(intent, BIOMETRIC_REQUEST);
    }

    protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
    {

        BiometricEventHandler?.Invoke(
            this,
            new BiometricEventArgs(
                true, new byte[] {1, 2, 3}
            );

        Finish();
        
    }
}

上面的代码抛出一个 NullReferenceException:

0xFFFFFFFFFFFFFFFF in System.Diagnostics.Debugger.Mono_UnhandledException_internal
0x1 in System.Diagnostics.Debugger.Mono_UnhandledException at /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/corlib/System.Diagnostics/Debugger.cs:125,4
0x20 in Android.Runtime.DynamicMethodNameCounter.57
0x6 in Xamarin.Forms.Platform.Android.PlatformConfigurationExtensions.OnThisPlatform<Xamarin.Forms.Application> at D:\a\_work\s\Xamarin.Forms.Platform.Android\PlatformConfigurationExtensions.cs:8,4
0xC in Xamarin.Forms.Platform.Android.AppCompat.FragmentContainer.OnResume at D:\a\_work\s\Xamarin.Forms.Platform.Android\AppCompat\FragmentContainer.cs:126,4
0x8 in AndroidX.Fragment.App.Fragment.n_OnResume at C:\a\_work\s\generated\androidx.fragment.fragment\obj\Release\monoandroid12.0\generated\src\AndroidX.Fragment.App.Fragment.cs:2570,4
0x11 in Android.Runtime.DynamicMethodNameCounter.57

和控制台:

**System.NullReferenceException:** 'Object reference not set to an instance of an object.'

我将其缩小到 Finish() 方法。 不调用也不例外

我尝试使用 BroadcastReceiver 从处理程序调用 Finish(),结果相同。

为什么 Finish() 抛出这个异常?

好吧,问题似乎是异步竞争条件。 Finish() 比 return 数据的服务需要更长的时间才能完成。

然后内容页面尝试执行 UI 事件,由于 Finish() 尚未完成,activity 仍然“可见”并且内容页面不可见还负责 UI 线程。因此 UI 事件失败并出现异常。

由于 await 调用 Finish() 似乎没有简单的方法,我使用 Task.Await 将 UI 事件延迟了一点, Finish() 完成。

不理想,但至少NullReferenceException没了