2015-12-08 97 views
0

我的源代碼中存在一個問題,它使異步方法不是模態。 我使用Mahapps新城框架和我有一個記錄器級有兩個異步方法吧:C#異步方法未運行模式

public class Logger : ILogger { 

    public void outputMessage(string message) { 
     Console.WriteLine(message); 
    } 

    public void outputUserMessage(string message) { 
     MessageBox.Show(message); 
    } 

    public async void outputMetroUserMessage(object window, String title, String message) { 
     MetroWindow mWindow = (MetroWindow)window; 
     await mWindow.ShowMessageAsync(title, message); 
    } 

    public async void outputMetroUserMessageWithHidingMDI(object window, string title, string message) { 
     UIGlobals.MainPageMdiChild.Visibility = Visibility.Hidden; 
     MetroWindow mWindow = (MetroWindow)window; 
     await mWindow.ShowMessageAsync(title, message); 
     UIGlobals.MainPageMdiChild.Visibility = Visibility.Visible; 
    } 
} 

還有一些其他類與調用記錄器方法的方法。例如:

public partial class Login : MetroWindow { 
    public Login() { 
     InitializeComponent(); 
    } 

    private void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { 
     DoLogin();    
    } 

    private void DoLogin() { 
     String email = txtEMail.Text; 
     String password = txtPassword.Password; 

     if (String.IsNullOrWhiteSpace(email)) { 
      Globals.Logger.outputMetroUserMessage(this, UserErrorMessageController.GetTitleByID(103), UserErrorMessageController.GetMessageByID(103)); 
     } else if (String.IsNullOrWhiteSpace(password)) { 
      Globals.Logger.outputMetroUserMessage(this, UserErrorMessageController.GetTitleByID(104), UserErrorMessageController.GetMessageByID(104)); 
     } else { 

      . 
      . 
      . 
     } 
    } 
} 

ProfileCreator:

public partial class ProfileCreator : MetroWindow { 

    public ProfileCreator(Network tempNetwork, UserProfile tempProfile) { 
     InitializeComponent(); 
     . 
     . 
     . 
    } 



    private void btnSave_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { 
     // TODO: Set cancelling when someting is missing 

     Save(); 
    } 

    private void Save() { 
     getUserProfileValuesFromWindow(); 

     Globals.TheSerializer.Serialize(tempProfile, Globals.PathToTemporaryFiles + "MyProfile.xml"); 

     tempNetwork.NetworkParticipants.Add(tempProfile.ParticipantID); 

     Globals.TheSerializer.Serialize(tempNetwork, Globals.PathToTemporaryFiles + "MyNetwork.xml"); 

     Globals.Logger.outputMetroUserMessage(this, "Erfolg", "Ihr Testsystem wurde erfolgreich angelegt.\nDrücken Sie erneut auf \"Testen\" und loggen Sie sich ein."); 
     Globals.Logger.outputMetroUserMessage(this, UserErrorMessageController.GetTitleByID(104), UserErrorMessageController.GetMessageByID(104)); 
    } 

當我打電話登錄級中的記錄器的方法,這些方法運行模式符合市場預期,但如果我把他們從ProfileCreator,他們似乎並不成爲模態。我試圖找出它,但我看不出類和參數的任何區別。也許你會看到我沒有的東西。

感謝您的幫助!

+0

當您通過\nDrücken時,您很可能會看到您未看到的錯誤。嘗試使用@「Ihr Testsystem wurde erfolgreich轉義整個字符串... –

回答

2

問題是您沒有使用Task。最佳做法是從所有async方法中返回Task,這些方法不會從WPF中的用戶單擊事件調用。您的代碼應該是這樣的:

public class Logger : ILogger 
{ 
    public void outputMessage(string message) 
    { 
     Console.WriteLine(message); 
    } 

    public void outputUserMessage(string message) 
    { 
     MessageBox.Show(message); 
    } 

    public Task<MessageDialogResult> outputMetroUserMessage(object window, String title, String message) 
    { 
     MetroWindow mWindow = (MetroWindow)window; 
     return mWindow.ShowMessageAsync(title, message); 
    } 

    public async Task outputMetroUserMessageWithHidingMDI(object window, string title, string message) 
    { 
     UIGlobals.MainPageMdiChild.Visibility = Visibility.Hidden; 
     MetroWindow mWindow = (MetroWindow)window; 
     await mWindow.ShowMessageAsync(title, message); 
     UIGlobals.MainPageMdiChild.Visibility = Visibility.Visible; 
    } 
} 

和使用它作爲這樣的:

public partial class Login : MetroWindow 
{ 
    public Login() 
    { 
     InitializeComponent(); 
    } 

    private async void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     await DoLogin(); 
    } 

    private async Task DoLogin() 
    { 
     String email = txtEMail.Text; 
     String password = txtPassword.Password; 

     if (String.IsNullOrWhiteSpace(email)) 
     { 
      await Globals.Logger.outputMetroUserMessage(this, UserErrorMessageController.GetTitleByID(103), UserErrorMessageController.GetMessageByID(103)); 
     } 
     else if (String.IsNullOrWhiteSpace(password)) 
     { 
      await Globals.Logger.outputMetroUserMessage(this, UserErrorMessageController.GetTitleByID(104), UserErrorMessageController.GetMessageByID(104)); 
     } 
     else 
     { 
      // ... 
     } 
    } 
} 

請注意,我只是從UI事件處理程序使用async void,這應該是你使用的唯一的地方那種模式。請通讀this進行解釋。

這裏是最後一部分,再次不要使用async void,除非你是從UI交互事件處理程序的方法。

public partial class ProfileCreator : MetroWindow 
{ 
    public ProfileCreator(Network tempNetwork, UserProfile tempProfile) 
    { 
     InitializeComponent(); 
     // ... 
    } 

    async void btnSave_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     // TODO: Set cancelling when someting is missing 
     await Save(); 
    } 

    async Task Save() 
    { 
     getUserProfileValuesFromWindow(); 

     Globals.TheSerializer.Serialize(tempProfile, Globals.PathToTemporaryFiles + "MyProfile.xml"); 

     tempNetwork.NetworkParticipants.Add(tempProfile.ParticipantID); 

     Globals.TheSerializer.Serialize(tempNetwork, Globals.PathToTemporaryFiles + "MyNetwork.xml"); 

     await Globals.Logger.outputMetroUserMessage(this, "Erfolg", "Ihr Testsystem wurde erfolgreich angelegt.\nDrücken Sie erneut auf \"Testen\" und loggen Sie sich ein."); 
     await Globals.Logger.outputMetroUserMessage(this, UserErrorMessageController.GetTitleByID(104), UserErrorMessageController.GetMessageByID(104)); 
    } 
} 
+0

但是這並不能解釋,爲什麼從Login登錄時該方法是模態的,而當ProfileCreator調用時不是模態。 –

+0

也許這與您的操作有關'UIGlobals',這在我看來是一個非常重要的問題,但是以前的方式,它可能會產生意想不到的結果 - 異步void本質上是失敗的,這意味着你不知道什麼是 –

+0

儘管如此,你的代碼完美無缺。非常感謝 –

1

那是因爲你打電話給你的異步方法「outputMetroUserMessage」兩次,而無需等待第一個的結果。你可以重新定義你的方法是這樣的:

public Task<MessageDialogResult> OutputMetroUserMessage(object window, string title, string message) 
{ 
    MetroWindow mWindow = (MetroWindow)window; 
    return mWindow.ShowMessageAsync(title, message); 
} 

,比等待消息輸出:

private async void button1_Click(object sender, RoutedEventArgs e) 
     { 
      await this.OutputMetroUserMessage(this, "Title", "Message1"); 
      await this.OutputMetroUserMessage(this, "Title", "Message2"); 
     } 

第二呼叫將由用戶acknowlegded的消息後執行。

希望有幫助。

+0

也是一個可行的答案。感謝您的幫助 –