连接时如何放置取消按钮

时间:2018-09-03 01:29:19

标签: c#

我在C#中使用登录名和密码进行连接,我想 放置一个按钮以取消与数据库的连接(如果连接过多) 长。

我想知道如何做,并尽可能将其放入线程中。

代码如下:

private void btncon_Click(object sender, EventArgs e)
{
    string strLogin = tblogin.Text.Trim();
    string pass  = tbpwd.Text;
    bool success = false;

    if (String.IsNullOrWhiteSpace(strLogin) || String.IsNullOrWhiteSpace(pass))
    {
        MessageBox.Show("Veuillez remplir tous les champs SVP ");
    }
    else if(String.IsNullOrEmpty(strLogin) || String.IsNullOrEmpty(pass)){
        MessageBox.Show("Veuillez remplir tous les champs SVP ");
    }
    else
    {
        model.Connexion cm = new model.Connexion();
        pass = Snippets.SHA1Util.SHA1HashStringForUTF8String(pass).ToString();
        string[] user = cm.login(strLogin, pass);    

        if(user[0] != null)
        {
            Int32.TryParse(user[0], out iduser);
            Int32.TryParse(user[1], out idGrp);
            Int32.TryParse(user[2], out idbtq);
            nom = user[3];

            if (idGrp != 3)
                success = true;
            else
            {
                MessageBox.Show("Accès Non autorisé , Veuillez contacter l'administrateur");
                success = false;
            }
        }
        else
        {
            MessageBox.Show("Email ou mot de passe incorrect.");
            success = false;
        }
    }

    if (success)
    {                
        main Principale = new main();
        Principale.Show();
        Hide();`
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于,当用户单击Cancel按钮时,无法在执行过程中优雅地取消cm.login()方法。您可以使用Thread.Abort()强制终止登录,但这是不安全的,强烈建议不要这样做,因为正确进行登录将需要在另一个AppDomain中执行代码,并且会使代码变得非常复杂。

幸运的是,如果满足以下条件,您仍然可以实现Cancel按钮:

  • 在另一个线程上调用cm.login()是安全的
  • 在用户单击cm.login()按钮之后,在后台(在另一个线程上)使Cancel保留在后台(没有其他效果)。

此代码还假定它是一个Winform应用程序(但是WPF应用程序的解决方案非常相似)。它还假定主窗体具有一个隐藏的按钮btnCancelVisible = false),并且其Click事件处理程序设置为btnCancel_Click方法。 / p>

TaskCompletionSource<Object> CancelLoginTcs = new TaskCompletionSource<Object>();

// Make button click handler method async
private async void btncon_Click(object sender, EventArgs e)
{
    try
    {
        // Make Cancel button visible, so that user can click on it
        btnCancel.Visible = true;

        // Prepare everything needed to start login
        //var strLogin = ...;
        //var pass = ...;
        //model.Connexion cm = new model.Connexion();
        // ...

        // Start login on another thread
        var loginTask = Task<string[]>.Run(() => cm.login(strLogin, pass));

        // Create task that is used to wake-up main thread, when user clicks
        // on the Cancel button before login finishes.
        CancelLoginTcs = new TaskCompletionSource<Object>();

        // Wait for login task or cancel task to complete, whichever finishes first
        await Task.WhenAny(loginTask, CancelLoginTcs.Task);

        if (CancelLoginTcs.Task.IsCanceled)
        {
            // User clicked on the Cancel button.
            // Login method will be running in the background, until it
            // finishes. This assumes that it is safe to do so.
            // Here you should do neccessary clean-up, inform user, etc.
            // ...
        }
        else
        {
            // Login finished and user did NOT click on the Cancel button.

            try
            {
                // Simply read result of login. If an Exception occured during login,
                // it will be rethrow now, so you should handle it appropriatelly
                var user = loginTask.Result;

                // Here program continues in a usual way
                // ...
            }
            catch(Exception E)
            {
                // Handle login exception
                // ...
            }
        }
    }
    finally
    {
        // Hide Cancel button again
        btnCancel.Visible = false;
        CancelLoginTcs = null;
    }
}

private void btnCancel_Click(object sender, EventArgs e)
{
    // Set cancel task to cancelled state. 
    // This will wake-up main thread and let it continue
    CancelLoginTcs.SetCanceled();
}