0

我已经解决了很多问题并阅读了示例和答案,但我似乎仍然无法理解如何正确实现这一目标。

我有一个按钮,用于切换外部登录/注销功能(从 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;
    }
}
4

0 回答 0