2013-11-03 36 views
0

我在WPF應用程序中使用異步方法時遇到問題。我想在我的WPF應用程序中實現異步等待模式,以便在使用EntityFramework查詢數據庫時保持表單響應性。我按照Microsoft示例中所述完成了所有操作,但它不會像應用程序那樣將控制流返回給應用程序。異步方法不會將控制流返回到表格

這裏是我的按鈕,單擊代碼:

private async void LoginButton_Click(object sender, RoutedEventArgs e) 
{ 
    var loggedIn = await _gluUserRepository.LoginAsync(LoginTextBox.Text, PasswordTextBox.Text); 

    Switcher.Switch(new Loader()); 
    if (loggedIn) 
    { 
     UserName = LoginTextBox.Text; 
     Switcher.Switch(new Blank()); 
    } 
    else 
    { 
     UserName = String.Empty; 
     MessageBox.Show("Błędny login lub hasło. Spróbuj ponownie."); 
     Switcher.Switch(new Login()); 
    } 
} 

這裏是我的LoginAsync方法:

public async Task<bool> LoginAsync(string login, string password) 
{ 
    string hashedPassword = PasswordHasher.Hash(password); 
    var user = await _dbContext.Users.FirstOrDefaultAsync(x => x.UserName == login); 
    if (user != null && user.Password == hashedPassword) 
     return true; 
    return false; 
} 

我見過異步的相同的使用/等待微軟的應用實例,但是,他們的WPF應用程序將控制返回到窗口句柄,即我可以在應用程序中移動窗口,這是不可能的。

我想要實現的是使用WPF應用程序的異步/等待模式來保持應用程序的響應。我想在查詢數據庫時顯示加載循環,查詢完成時返回方法。

任何人有一個想法我做錯了什麼?

+0

與論壇網站不同,我們不使用「謝謝」或「任何幫助讚賞」,或在[so]上簽名。請參閱「[應該'嗨','謝謝',標語和致敬從帖子中刪除?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be –

+0

如果您發現問題的解決方案,您應該將其作爲*答案*發佈,而不是編輯該問題。 – Servy

回答

0

我找到了解決方案。雖然我不知道它爲什麼會起作用。但它不會阻塞UI線程。我不認爲它也是線程安全的,你應該感到疲倦。

private async void LoginButton_Click(object sender, RoutedEventArgs e) 
     { 
      var loginTask = userRepository.LoginAsync(LoginTextBox.Text, PasswordTextBox.Password); 
      controller.DisplayPageLoader(); 
      DbUser loginResult = await loginTask; 
      if (loginResult != null) 
      { 
       controller.DisplayPageNewMeal(); 
       controller.SetLoggedUser(loginResult); 
      } 
      else 
      { 
       MessageBox.Show("Błędny login lub hasło. Spróbuj ponownie."); 
       controller.DisplayPageLogin(); 
      } 
     } 

,然後在儲存庫

public Task<DbUser> LoginAsync(string login, string password) 
     { 
      return Task.Run<DbUser>(() => Login(login, password)); 
     } 

private DbUser Login(string login, string password) 
     { 
      try 
      { 
       string hashedPassword = PasswordHasher.Hash(password); 
       var user = _dbContext.Users.FirstOrDefaultAsync(x => x.UserName == login); 
       if (user.Result != null && user.Result.Password == hashedPassword) 
        return user.Result; 
       return null; 
      } 
      catch(Exception ex) 
      { 
       _logger.Error("Blad logowania uzytkownika", ex); 
       return null; 
      } 
     } 
0

如果我理解正確

Switcher.Switch(new Loader()); 

就是顯示 '加載圈子'。

你需要稱之爲之前await的登錄。現在,您的處理程序會在LoginAsync返回後執行其他所有操作。您可能還想看看ReactiveUI。它提供瞭解決您的問題的有用框架。

+0

是的,您理解正確,但是,我試圖在等待它仍然阻塞主線程,我不能移動主窗口任何地方 – VsMaX

+1

我懷疑有其他東西阻塞或更可能使UI線程陷入麻煩,使它無響應當你擺脫除了等待呼叫之外的所有東西時會發生什麼? – majocha

+0

它仍然阻止,所以我猜這是在某個地方。 – VsMaX

0

很難做出猜測,但嘗試改變你的LoginButton_Click碼開始後,開始了它的結果,任務和await,像這樣:

private async void LoginButton_Click(object sender, RoutedEventArgs e) 
{ 
    var loggedInTask = _gluUserRepository.LoginAsync(LoginTextBox.Text, PasswordTextBox.Text); 

    MessageBox.Show("before await"); 
    var loggedIn = await loggedInTask; 
    MessageBox.Show("after await"); 

    // ... 
} 

你應該之後會看到兩個消息框,一個另一個,他們都應該是有迴應性的,即可移動和可點擊。如果您確實看到了這種行爲,那麼問題很可能與您的Switcher.Switch有關,並且與EntityFramework的異步方法無關。

0

我有主要形式與異步加載方法:

私人異步空隙MainMenu_Load(對象發件人,EventArgs的) { 等待_connection.Start( ); await _myHub.Invoke(「Join」); (「已收到」,數據=> var obj = JsonConvert。DeserializeObject(數據);

  messagewindows = new SendMessage(User, obj.Sender); 


       if ((obj.Reciever == User)) 
       { 
        messagewindows. txtHistory.Text += obj.Sender + " :" + obj.text + Environment.NewLine; 
        messagewindows.Show(); 
       } 



     }); 

    } 

我示出了用於顯示消息,但形式掛起崩潰應用第二種形式:

私人異步空隙SendMessage_Load(對象發件人,EventArgs的) { 文本= Reciever;

 await _connection.Start(); 
     await _myHub.Invoke("Join"); 



     _myHub.On("recieved", data => 
     { 
      var obj = JsonConvert.DeserializeObject<MessageSent>(data); 
      if ((obj.Reciever == Sender || obj.Sender == Sender) && (obj.Sender == Reciever || obj.Reciever == Reciever)) 
      { 


        txtHistory.Text += obj.Sender + " :" + obj.text + Environment.NewLine; 

        txtHistory.SelectionStart = txtHistory.Text.Length; 
        txtHistory.ScrollToCaret(); 

      } 
     }); 

    }