Reputation: 63
I'm trying to use the WIN10 api in WPF, to authenticate users.
I'm using the sample code from 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;
}
The CheckAvailabilityAsync()
is working fine.
The RequestVerificationAsync()
calls the api and the modal dialog is shown, but after authentication the modal dialog disappears and the application is still waiting for result...
Also tried building the app and running it as administrator, but still no results.
I'm missing something?
Upvotes: 0
Views: 903
Reputation: 74
This is a common problem in certain environments, especially in UI applications like WinForms or WPF, where the UI thread can get blocked when using async/await improperly.
When you use await in an environment that relies on a single-threaded synchronization context (like the UI thread), the await by default tries to marshal the continuation back to the original synchronization context (the UI thread). If the UI thread is blocked, this creates a deadlock because the continuation cannot be executed.
The correct and more robust solution is to tell the await to not capture the current synchronization context. You can do this by adding .ConfigureAwait(false) to the await call.This ConfigureAwait(false) tells the await not to marshal the continuation back to the original context (which could be the UI thread in your case), avoiding the deadlock.
When you're working in a UI thread or other contexts where thread synchronization is involved, ConfigureAwait(false) ensures that your continuation doesn’t try to resume on the same thread, avoiding deadlocks. It also improves the performance by skipping the overhead of marshaling the continuation back to the original synchronization context.
IAsyncOperation (from the Windows Runtime API) does not directly support the ConfigureAwait method, which is designed for use with Task or Task in .NET. UserConsentVerifier.RequestVerificationAsync returns an IAsyncOperation, which is specific to Windows Runtime (WinRT) asynchronous programming and isn't directly compatible with the typical Task-based ConfigureAwait mechanism in C#. To resolve this issue, you can convert the IAsyncOperation to a Task using the .AsTask() method, which allows you to use it with ConfigureAwait(false).
var consentResult = await Windows.Security.Credentials.UI.UserConsentVerifier.RequestVerificationAsync(userMessage).AsTask().ConfigureAwait(false);
Upvotes: 0
Reputation: 79
In the method call try this, it worked for me
var res = RequestConsent("Please provide fingerprint verification.").Result;
Upvotes: 0