为什么我的UI没有响应?

时间:2015-09-07 21:18:56

标签: c# wpf

我的登录窗口高度反应迟钝。我不确定为什么会这样。我正在使用MVVM light作为我的MVVM框架。我处理登录按钮点击RelayCommand,命令处理程序(我知道将整个PasswordBox作为参数传递是不好的做法,它打破了MVVM模式,但请关注这个问题)。命令处理程序如下:

LoginButtonClicked = new GalaSoft.MvvmLight.Command.RelayCommand<System.Windows.Controls.PasswordBox>((pwdBox) =>
{
    if (string.IsNullOrWhiteSpace(this.Username) || string.IsNullOrWhiteSpace(pwdBox.Password))
    {
        MessageBoxRequested("Neuspešno logovanje", "Molimo unesite i korsničko ime i lozinku");
        return;
    }

    ProgressDialogRequested();

    bool validated = false;

    try
    {
        validated = TotalSport.Framework.UserManagement.EmployeeStore.ValidateEmployee(this.Username, pwdBox.Password);
    }
    catch (System.Data.Entity.Core.ObjectNotFoundException)
    {
        MessageBoxRequested("Logovanje neuspešno", "Zaposleni sa tim imenom ne postoji!");
        pwdBox.Password = string.Empty;
        return;
    }

    pwdBox.Password = string.Empty;

    System.Diagnostics.Debug.WriteLine(validated);

    if (validated)
    {
        Client.Views.MainWindow mw = new Client.Views.MainWindow(this.Username);
        mw.Show();
        CloseRequested();
    }
    else
        MessageBoxRequested("Logovanje neuspešno", "Pogrešna lozinka!");
});

ValidateEmployee对提供的字符串进行哈希处理,并将其与存储在数据库中的值进行比较。我认为这是我的问题的原因(很可能是因为它是一个缓慢的哈希 - PBDKF2 - 以及单个方法中的数据库查询),但我不确定为什么。它与UI线程和LoginWindow本身无关。

实际窗口上的相关事件处理程序:

((ViewModels.LoginViewModel)this.DataContext).MessageBoxRequested += (title, message) =>
{
    this.ShowMessageAsync(title, message);
};
((ViewModels.LoginViewModel)this.DataContext).ProgressDialogRequested += () =>
{
    this.ShowProgressAsync("Test", "test");
};
((ViewModels.LoginViewModel)this.DataContext).CloseRequested += () =>
{
    this.Close();
};

关于此的任何输入?

1 个答案:

答案 0 :(得分:2)

在LoginButtonClicked处理程序中,使用以下代码:

var username = this.Username;

var password = pwdBox.Password;

Task.Factory.StartNew(() => //This will run using a Thread-Pool thread which will not cause the UI to be unresponsive.
{
    //Do expensive operations here, like data access
    //You cannot access the UI here

    bool valid = DoSomeExpensiveCallsToDetermineIfPasswordIsValid(username, password);

    return valid;
})
.ContinueWith( t => //This will run on the UI thread
{

    bool valid = t.Result;

    if (valid)
    {
        //Do some UI to indicate that the password is valid
    }
    else
    {
        //Do some UI to indicate that the password is not valid
    }


}, CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion, //Only run this if the first action did not throw an exception
TaskScheduler.FromCurrentSynchronizationContext()); //Use the UI thread to run this action

此代码假定DoSomeExpensiveCallsToDetermineIfPasswordIsValid不会抛出异常。处理此类方法中的任何异常。

此代码使用后台线程运行第一个操作,然后使用UI线程中的第二个操作。

在UI线程中运行的代码应该很快。