I am having a issue accesing a text box in a view controller .cs file
async partial void loginUser(UIButton sender)
{
// Show the progressBar as the MainActivity is being loade
Console.WriteLine("Entered email : " + txtEmail.Text);
// Create user object from entered email
mCurrentUser = mJsonHandler.DeserialiseUser(txtEmail.Text);
try
{
Console.WriteLine("Starting network check");
// Calls email check to see if a registered email address has been entered
if (EmailCheck(txtEmail.Text) == true)
{
await CheckPassword();
}
else
{
UIAlertView alert = new UIAlertView()
{
Title = "Login Alert",
Message = "Incorrect email or password entered"
};
alert.AddButton("OK");
alert.Show();
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("An error has occured: '{0}'", ex);
}
It is within this funciton that it complains it cannot access a text box which is on a aynsc method
public Task CheckPassword()
{
return Task.Run(() =>
{
// Creates instance of password hash to compare plain text and encrypted passwords.
PasswordHash hash = new PasswordHash();
// Checks password with registered user password to confirm access to account.
if (hash.ValidatePassword(txtPassword.Text ,mCurrentUser.password)==true)
{
Console.WriteLine("Password correct");
UIAlertView alert = new UIAlertView()
{
Title = "Login Alert",
Message = "Password Correct Loggin In"
};
alert.AddButton("OK");
alert.Show();
//insert intent call to successful login here.
}
else
{
UIAlertView alert = new UIAlertView()
{
Title = "Login Alert",
Message = "Incorrect email or password entered"
};
alert.AddButton("OK");
alert.Show();
}
Console.WriteLine("Finished check password");
});
}
Its this line the error occurs:
txtPassword.Text
The error is as follows:
UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.
Also my Password Correct does not show even though if it is a correct password. Do i have to run the UI Alerts on a seperate thread?
Any UIKit methods must be called from the UI thread (or Main thread, Main queue, etc.). This ensures consistency in the UI. Xamarin adds a check to all UIKit methods in debug mode and throws that exception if you try to use a background thread to change the UI.
The solution is simple: only modify the UI from the UI thread. That essentially means if you're using a class with "UI" in front it, you should probably do it from the UI thread. (That's a rule of thumb and there are other times to be on the UI thread).
How do I get my code on this mythical UI thread? I'm glad you asked. In iOS, you have a few options:
InvokeOnMainThread
will do the trick.CoreFoundation.DispatchQueue.MainQueue.DispatchAsync
will always work.Both of those methods just accept an Action
, which can be a lambda or a method.
So in your code, if we add an InvokeOnMainThread
(because I think this is in your UIViewController
subclass)...
public Task CheckPassword()
{
return Task.Run(() =>
{
// Creates instance of password hash to compare plain text and encrypted passwords.
PasswordHash hash = new PasswordHash();
// Checks password with registered user password to confirm access to account.
InvokeOnMainThread(() => {
if (hash.ValidatePassword(txtPassword.Text ,mCurrentUser.password)==true)
{
Console.WriteLine("Password correct");
UIAlertView alert = new UIAlertView()
{
Title = "Login Alert",
Message = "Password Correct Loggin In"
};
alert.AddButton("OK");
alert.Show();
//insert intent call to successful login here.
}
else
{
UIAlertView alert = new UIAlertView()
{
Title = "Login Alert",
Message = "Incorrect email or password entered"
};
alert.AddButton("OK");
alert.Show();
}
});
Console.WriteLine("Finished check password");
});
}
Maybe this helps someone. So I will add what solve my issue, that was the same of rogue. Follow the code that avoid this error of consistency in xamarin forms when used in iOS
await Task.Run(async () =>
{
await Device.InvokeOnMainThreadAsync(async () =>
{
await MaterialDialog.Instance.SnackbarAsync(message: "Bla bla bla",
msDuration: MaterialSnackbar.DurationShort).ConfigureAwait(false);
}).ConfigureAwait(false);
}).ConfigureAwait(false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With