我创建了一个生物识别身份验证服务,它启动一个活动,并为结果注册一个回调到静态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;
}
}
和活动(显然不是实际代码):
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_work1sXamarin.Forms.Platform.AndroidPlatformConfigurationExtensions.cs:8,4
0xC in Xamarin.Forms.Platform.Android.AppCompat.FragmentContainer.OnResume at D:a_work1sXamarin.Forms.Platform.AndroidAppCompatFragmentContainer.cs:126,4
0x8 in AndroidX.Fragment.App.Fragment.n_OnResume at C:a_work1sgeneratedandroidx.fragment.fragmentobjReleasemonoandroid12.0generatedsrcAndroidX.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()
完成的时间比服务返回数据的时间稍长。
然后内容页尝试执行UI事件,并且由于Finish()
尚未完成,该活动仍然是"可见"的;内容页还不负责UI线程。因此UI事件失败并产生异常。
由于似乎没有一种简单的方法来await
Finish()
调用,我使用Task.Await
来延迟UI事件一点,并完成Finish()
。
不理想,但至少NullReferenceException
不见了