我正在为大学做作业,要求是我必须使用多线程,现在每次我登录,我都要点击两次来改变主窗口的UI。知道我哪里做错了吗?
如果我使用user_login
方法的代码,它工作得很好,UI更新得很快,但是当我使用多线程时,我必须单击标签两次才能更改我的UI。
我使用按钮控件做了同样的事情,但对于上面给出的两个测试也有相同的结果。
private void tbLogin_MouseDown(object sender, MouseButtonEventArgs e)
{
//Assign Class Property Values
login.Student_Email = txtstd_Email.Text;
login.Student_Password = txtstd_Password.Password;
Thread user_login_thread = new Thread(() => User_Login(login.Student_Email,
login.Student_Password));
user_login_thread.Start();
if (login.UserLoggedIn)
{
foreach (Window window in Application.Current.Windows)
{
if (window.GetType() == typeof(MainWindow))
{
//Change page on login
(window as MainWindow).frmView.Source = new Uri("Views/Dashboard.xaml", UriKind.Relative);
}
}
}
user_login_thread.Join();
if (chkRemember.IsChecked == true)
{
Properties.Settings.Default.Student_Email = login.Student_Email;
Properties.Settings.Default.Student_Password = login.Student_Password;
Properties.Settings.Default.Save();
}
}
private void User_Login(string email, string password)
{
//Security object
Secure security = new Secure();
conn.Open();
string sql = "SELECT Student_Number, Student_FullName, Student_Email, Student_Password FROM
Student_Data WHERE Student_Email=@Email";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("@Email", System.Data.SqlDbType.VarChar, 55).Value = email;
cmd.Parameters.Add("@Pass", System.Data.SqlDbType.VarChar, 55).Value = password;
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read() &&
login.Student_Password.Equals(security.Decrypt(reader["Student_Password"].ToString())))
{
login.UserLoggedIn = true;
}
else
{
_ = MessageBox.Show("Login Unsuccessful", "Student Login Unsuccessfull",
MessageBoxButton.OKCancel, MessageBoxImage.Error);
}
}
conn.Close();
}
主要问题是在检查if (login.UserLoggedIn)
之前没有等待查询完成。
我建议你使用async
和await
来代替线程。
你还有其他一些问题:
- 连接和读取对象需要
using
块。 - 是否不缓存连接,创建一个新的当你需要它。
- 密码的可逆加密是一个坏主意,使用哈希代替。将哈希值传递给服务器进行验证,不要将其带回客户端应用程序。 当连接打开时,不要用消息框阻塞线程。
- 不要读过多的专栏。
- 如果你只有一列和一行,使用ExecuteScalar
private async void tbLogin_MouseDown(object sender, MouseButtonEventArgs e)
{
//Assign Class Property Values
login.Student_Email = txtstd_Email.Text;
login.Student_Password = txtstd_Password.Password;
await User_Login(login.Student_Email, login.Student_Password));
.....
private async Task User_Login(string email, string password)
{
//Security object
Secure security = new Secure();
const string sql = @"
SELECT 1
FROM Student_Data
WHERE Student_Email = @Email
AND Student_Password = @Pass;
";
using (var conn = new SqlConnection(yourConnString))
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("@Email", SqlDbType.VarChar, 55).Value = email;
cmd.Parameters.Add("@Pass", SqlDbType.VarChar, 55).Value = security.Encrypt(password);
await conn.OpenAsync();
login.UserLoggedIn = await comm.ExecuteScalarAsync() != null;
}
if (!login.UserLoggedIn)
{
_ = MessageBox.Show("Login Unsuccessful", "Student Login Unsuccessfull",
MessageBoxButton.OKCancel, MessageBoxImage.Error);
}
}