2017-03-17 59 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:不要*改變*你的方法;只是*添加*這一個。 –