2017-03-17 101 views
0

我使用MVVM光与有其中用于用于显示一个对话框接口IDialogService。此接口已经在App.xaml.cs已经实现C#等待关于GUI线程和捕获异常WPF

一种具体方法是有趣:

 public Task<bool> ShowMessage(string message, string title, string buttonConfirmText, 
     string buttonCancelText, 
     Action<bool> afterHideCallback) 
    { 
     return Task.Factory.StartNew(() => 
     { 
      var style = new Style(typeof(MessageBox)); 
      style.Setters.Add(new Setter(MessageBox.OkButtonContentProperty, buttonConfirmText)); 
      style.Setters.Add(new Setter(MessageBox.CancelButtonContentProperty, buttonCancelText)); 
      var result = MessageBox.Show(_GetActiveWindow(), message, title, 
       MessageBoxButton.OKCancel, 
       MessageBoxImage.Question, style) == MessageBoxResult.OK; 
      if (afterHideCallback != null) afterHideCallback(result); 
      return result; 

_currentTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();OnStartup

定义:

Task<bool> ShowMessage(string message, string title, string buttonConfirmText, string buttonCancelText, Action<bool> afterHideCallback); 

物的方法来实现

所以平时我们应该把这种方法与前面的await获得布尔值:

var result = await DialogService.ShowMessage(
         Resources.Areyousure,Resources.Warning, 
         Resources.Yes, Resources.No, null); 

到目前为止好。现在我有一个包装方法来执行代码并捕获异常,然后显示带有错误的消息框。

public bool TryCatchExecution(Action action, string successMessage = null) 
    { 
     try 
     { 
      action(); 

      if (!string.IsNullOrEmpty(successMessage)) 
       DialogService.ShowMessage(successMessage, Resources.Success); 
      return true; 
     } 
     catch (LogException ex) 
     { 
      DialogService.ShowError(ex.Error.LogMessage, Resources.Error, Resources.OK, null); 
     } 
     catch (Exception ex) 
     { 
      DialogService.ShowError(ex.Message, Resources.Error, Resources.OK, null); 
     } 
     return false; 
    } 

现在我有一个问题。如果我使用样本A,GUI线程在行var result = DialogService.ShowMessage处被阻止。但是,如果我使用示例B中的GUI线程未阻止,则会显示消息框,并且所有内容都按照它应该的方式工作。直到我得到一个异常。代码无例外。错误是“类型的第一个机会异常‘System.ServiceModel.FaultException`1’出现在mscorlib.dll”和应用程序崩溃。正如我一直在阅读的,这与SynchronizationContext有关。

//Sample A 
    private void ExecuteDeleteCommand() 
    { 
     TryCatchExecution(() => 
      { 
       var result = DialogService.ShowMessage(
        Resources.Areyousure, 
        Resources.Warning, 
        Resources.Yes, 
        Resources.No, null).Result; 
       if (!result) return; 

       _datalayer.DeleteField(FieldSelected); 
       Refresh(); 
       FieldEdit = new MsgSqlFieldMapping(); 
       RaisePropertyChanged("SqlRepository"); 
       DialogService.ShowMessage(Resources.OperationSucceeded, Resources.Success); 
      }); 
    } 

    //Sample B 
    private void ExecuteDeleteCommand() 
    { 
     TryCatchExecution(async() => 
     { 
      var result =await DialogService.ShowMessage(
       Resources.Areyousure, 
       Resources.Warning, 
       Resources.Yes, 
       Resources.No, null); 
      if (!result) return; 

      _datalayer.DeleteField(FieldSelected); 
      Refresh(); 
      FieldEdit = new MsgSqlFieldMapping(); 
      RaisePropertyChanged("SqlRepository"); 
      await DialogService.ShowMessage(Resources.OperationSucceeded, Resources.Success); 
     }); 
    } 

请帮我理解这里发生了什么,以及如何处理它。

日Thnx了很多。

+0

我已经忘了提,我使用.net4.5框架。 – Gintaras

回答

1

你的问题是由于async void - 具体而言,通过传递一个async lambda作为类型Action的参数,您正在创建一个async void方法。其中一个problems with async void methods的是,你不能捕获的异常(至少不正常的方式)。

要解决此问题,创建的helper方法的重载,是以async equivalent of Action, which is Func<Task>

public async Task<bool> TryCatchExecution(Func<Task> action, string successMessage = null) 
{ 
    try 
    { 
     await action(); 

     if (!string.IsNullOrEmpty(successMessage)) 
      DialogService.ShowMessage(successMessage, Resources.Success); 
     return true; 
    } 
    catch (LogException ex) 
    { 
     DialogService.ShowError(ex.Error.LogMessage, Resources.Error, Resources.OK, null); 
    } 
    catch (Exception ex) 
    { 
     DialogService.ShowError(ex.Message, Resources.Error, Resources.OK, null); 
    } 
    return false; 
} 
+0

嗨,感谢解决方案。有一个小问题。我已经检查过这个解决方案。问题是改变方法签名后,我需要改变大约200种其他方法。 – Gintaras

+1

@Gintaras:不要*改变*你的方法;只是*添加*这一个。 –