我正在尝试在WPF中使用WIN10 api来对用户进行身份验证。
我正在使用 Microsoft Docs 中的示例代码:
private async System.Threading.Tasks.Task<string> RequestConsent(string userMessage)
{
string returnMessage;
if (String.IsNullOrEmpty(userMessage))
{
userMessage = "Please provide fingerprint verification.";
}
try
{
// Request the logged on user's consent via fingerprint swipe.
var consentResult = await Windows.Security.Credentials.UI.UserConsentVerifier.RequestVerificationAsync(userMessage);
switch (consentResult)
{
case Windows.Security.Credentials.UI.UserConsentVerificationResult.Verified:
returnMessage = "Fingerprint verified.";
break;
case Windows.Security.Credentials.UI.UserConsentVerificationResult.DeviceBusy:
returnMessage = "Biometric device is busy.";
break;
case Windows.Security.Credentials.UI.UserConsentVerificationResult.DeviceNotPresent:
returnMessage = "No biometric device found.";
break;
case Windows.Security.Credentials.UI.UserConsentVerificationResult.DisabledByPolicy:
returnMessage = "Biometric verification is disabled by policy.";
break;
case Windows.Security.Credentials.UI.UserConsentVerificationResult.NotConfiguredForUser:
returnMessage = "The user has no fingerprints registered. Please add a fingerprint to the " +
"fingerprint database and try again.";
break;
case Windows.Security.Credentials.UI.UserConsentVerificationResult.RetriesExhausted:
returnMessage = "There have been too many failed attempts. Fingerprint authentication canceled.";
break;
case Windows.Security.Credentials.UI.UserConsentVerificationResult.Canceled:
returnMessage = "Fingerprint authentication canceled.";
break;
default:
returnMessage = "Fingerprint authentication is currently unavailable.";
break;
}
}
catch (Exception ex)
{
returnMessage = "Fingerprint authentication failed: " + ex.ToString();
}
return returnMessage;
}
CheckAvailabilityAsync()
工作正常。 RequestVerificationAsync()
调用 api 并显示模式对话框,但身份验证后模式对话框消失,应用程序仍在等待结果... 在方法调用中尝试这个,它对我有用
var res = RequestConsent("Please provide fingerprint verification.").Result;
这是某些环境中的常见问题,尤其是在 WinForms 或 WPF 等 UI 应用程序中,如果不正确地使用 async/await,UI 线程可能会被阻塞。
当您在依赖单线程同步上下文(如 UI 线程)的环境中使用 wait 时,默认情况下,await 会尝试将延续封送回原始同步上下文(UI 线程)。如果 UI 线程被阻塞,则会造成死锁,因为无法执行延续。
正确且更稳健的解决方案是告诉await不要捕获当前同步上下文。您可以通过将 .ConfigureAwait(false) 添加到await 调用来完成此操作。此ConfigureAwait(false) 告诉await 不要将延续封送回原始上下文(在您的情况下可能是UI 线程),从而避免死锁。
当您在 UI 线程或涉及线程同步的其他上下文中工作时,ConfigureAwait(false) 可确保您的延续不会尝试在同一线程上恢复,从而避免死锁。 它还通过跳过将延续封送回原始同步上下文的开销来提高性能。
IAsyncOperation(来自Windows运行时API)不直接支持ConfigureAwait方法,该方法设计用于与Task或.NET中的Task一起使用。 UserConsentVerifier.RequestVerificationAsync 返回 IAsyncOperation,它特定于 Windows 运行时 (WinRT) 异步编程,并且与 C# 中典型的基于任务的 ConfigureAwait 机制不直接兼容。要解决此问题,您可以使用 .AsTask() 方法将 IAsyncOperation 转换为任务,该方法允许您将其与ConfigureAwait(false) 一起使用。
var consentResult = await Windows.Security.Credentials.UI.UserConsentVerifier.RequestVerificationAsync(userMessage).AsTask().ConfigureAwait(false);