我已经解决了很多问题并阅读了示例和答案,但我似乎仍然无法理解如何正确实现这一目标。
我有一个按钮,用于切换外部登录/注销功能(从 DLL 导入并包装在一个类中) - 此登录可能需要大约 10 秒才能完成。此函数运行时,主窗体挂起。
我想做的是从此登录功能返回成功/失败,然后用结果更新 UI。与此同时,在登录功能正在处理的同时,UI 线程不应被阻塞。
我的按钮代码在这里(请原谅我的糟糕代码,我还是个初学者):
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;
}
我理解这应该起作用的方式(如果我正确阅读所有这些帖子,尤其是这个),是按钮代码应该一直执行到await
语句,在后台启动任务,然后有效地返回并处理消息泵,直到等待的任务 ping,说“我准备好了”,并将其余的方法排队等待执行。
实际上,此函数会阻塞 UI 线程,直到任务返回并继续执行。
老实说,我对此束手无策,我尝试创建一个单独的异步任务并等待它,在类内部执行所有异步函数(目前类方法不是异步的),以及一个整体许多其他我不记得的不起作用的东西。
类方法在这里(外部DLL函数是调用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;
}
}