2015-12-08 99 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

也是一个可行的答案。感谢您的帮助 –