I have been through quite a number of questions and read through the examples and answers, yet I still can't seem to wrap my head around how to achieve this properly.
I have a button which toggles an external Login / Logout function (imported from a DLL and wrapped in a class) - this login can take up to about 10 seconds to complete. While this function is running, the main Form hangs.
What I would like to do is return a success / fail from this login function, then update the UI with the result. In the meantime while the login function is processing, the UI thread shouldn't be blocked.
My button code is here (please forgive my bad code, I am still very much a beginner):
private async void btnConnect_Click(object sender, EventArgs e)
{
btnConnect.Enabled = false;
if (pw.Initialised)
{
bool isLoggedIn = pw.LoggedIn;
if (isLoggedIn)
{
isLoggedIn = await Task.Run(() => pw.LogOut());
if (!isLoggedIn)
{
lblConnection.Text = "Disconnected";
lblDataSource.Text = "N/A";
lblUserName.Text = "N/A";
lblAdmin.Text = "N/A";
btnConnect.Text = "Connect";
btnChooseSet.Enabled = false;
}
}
else
{
string dataSourceName = cbDataSource.SelectedItem.ToString();
IntPtr formHandle = Handle;
bool autoLogin = cbAutoLogin.Checked;
isLoggedIn = await Task.Run(() => pw.LogIn(dataSourceName, autoLogin,
formHandle));
if (isLoggedIn)
{
lblConnection.Text = "Connected";
lblDataSource.Text = pw.CurrentDataSource;
lblUserName.Text = pw.CurrentUser.UserName;
lblAdmin.Text = pw.CurrentUser.IsAdmin.ToString();
btnConnect.Text = "Disconnect";
btnChooseSet.Enabled = true;
}
}
}
btnConnect.Enabled = true;
}
The way I understand this should work (if I am reading all these posts correctly, especially this one), is that the button code should execute all the way up to the await
statement, fire off the task in the background, then effectively return and process the message pump until the awaited task pings, says "I'm ready", and queues up the rest of the method for execution.
In reality, this function blocks the UI thread until the task returns and execution continues.
I'm at my wits end with this to be honest, I've tried creating a separate async task and awaiting that, doing all the async functions inside of the class (at the moment the class method is not async), and a whole host of other things that didn't work that I can't remember.
The class method is here (the external DLL function is the call to aaApi_LoginDlgExt
:
public bool LogIn(string dataSourceName, bool autoLogIn, IntPtr formHandle)
{
if (dataSourceName == null)
{
OnLogEvent("Select a datasource from the drop-down menu!");
return false;
}
int maxLen = 256;
StringBuilder sbDSName = new StringBuilder(dataSourceName, maxLen);
uint uiLoginFlags = 0x00000000;
if (autoLogIn)
{
uiLoginFlags |= (uint)LoginDialogStyleFlags.AALOGIN_SILENT;
}
if (aaApi_LoginDlgExt(formHandle, null, uiLoginFlags, sbDSName, maxLen,
null, null, null) == (int)DialogBoxCommandId.IDOK)
{
isLoggedIn = true;
currentDataSource = sbDSName.ToString();
currentDataSourceHandle = aaApi_GetActiveDatasource();
currentUser = new UserData();
OnLogEvent("Logged in");
return true;
}
else
{
OnLogEvent("Failed to Log In!");
return false;
}
}