2016-10-12 7 views
0

Mvvm light RelayCommand me cause un peu de mal de tête avec async méthodes. bouton WPF est à égalité avec la RelayCommand suivante:RelayCommand et la méthode asynchrone qui en résulte: "'System.Reflection.TargetInvocationException" s'est produite dans mscorlib.dll "

private RelayCommand _importDeviceCommand; 
    /// <summary> 
    /// Import device button for SelectDeviceView. 
    /// </summary> 
    public RelayCommand ImportDeviceCommand 
    { 
     get 
     { 
      return _importDeviceCommand 
        ?? (_importDeviceCommand = new RelayCommand(async() => await AddDeviceClickExecute(), 
         () => _selectedCableType != null 
          && _selectedAddDevice != null 
          && _selectedPointNames != null 
          && _selectedPointNames.Any())); 
     } 
    } 

Je suis probablement abusant sous une forme parce que garder la rencontre de temps en temps l'exception suivante toujours lorsque la méthode AddDeviceClickExecute est fait.

Une exception non gérée du type 'System.Reflection.TargetInvocationException' est produite dans mscorlib.dll

  • Quelles sont les solutions possibles?
  • Pourrait-il avoir quelque chose à voir avec les appels de méthode lambda?
  • Par conséquent, comment est-ce que je peux refactoriser la commande de relais de telle sorte que aucun lambda n'est employé?

EDIT 1

La méthode appelée async, le try/catch est malheureusement pas fait une différence?

private async Task AddDeviceClickExecute() 
     { 
      _linkTheSocket = true; 

      var deviceImporter = new DeviceImporterAsync2(_projectContext, _deviceContext); 

      var progress = new Progress<string>(status => 
      { 
       _importDeviceProgress = status; 
       RaisePropertyChanged("ImportDeviceProgress"); 
      }); 

      try 
      { 
       await deviceImporter.InvokeSimpleDeviceImport(UserSelectedSockets, progress); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.ToString(), "Exception during simple device import", MessageBoxButton.OK, MessageBoxImage.Error); 
      } 
     } 

EDIT 2

L'exception suivante se produit juste après les sorties AddDeviceClickExecute.

Image of the exception

EDIT 3

Tourné que la façon dont j'utilisait async et RelayCommand avait rien à voir avec mon exception. Le problème a été résolu.

+2

Il est rarement utile de dire quelque chose de 'TargetInvocationException' sans vérifier son 'InnerException'. –

+0

'InnerException' est vide ou je ne sais pas comment le voir. Sur les paramètres d'exception, j'ai activé les (Common Language Runtime Exections) J'utilise Visual Studio 2015. – ajr

+1

Vous pourriez avoir un peu de chance d'arriver à l'erreur réelle en faisant Visual Studio break au débogueur dès que l'exception est levée. Vous pouvez le faire à partir de la fenêtre d'exception, il suffit de cocher "Common Language Runtime", puis faites l'erreur. Assurez-vous de l'éteindre lorsque vous avez terminé, ce comportement peut devenir très ennuyeux. https://blogs.msdn.microsoft.com/visualstudioalm/2015/02/23/the-new-exception-settings-window-in-visual-studio-2015/ –

Répondre

2

Vous verrez une exception non gérée chaque fois que vous avez une exception échapper à une méthode async void (à savoir, le lambda vous passez à RelayCommand).

Ceci est un comportement normal et attendu; C'est le même comportement que vous verriez d'un lambda synchrone RelayCommand, à l'exception du wrapper TargetInvocationException. Comme d'autres l'ont noté, il suffit d'examiner le InnerException pour voir l'exception sous-jacente réelle.

Si vous voulez attraper ces exceptions, vous devez envelopper le corps entier de la méthode async void dans un try/catch. C'est possible mais un peu gênant dans un lambda:

return _importDeviceCommand 
    ?? (_importDeviceCommand = new RelayCommand(async() => 
     { try { await AddDeviceClickExecute(); } catch (Exception ex) { ... } }, 
    () => _selectedCableType != null 
     && _selectedAddDevice != null 
     && _selectedPointNames != null 
     && _selectedPointNames.Any())); 

Mais cela devient vraiment gênant IMO.Il est préférable de le diviser en une autre méthode:

private async void ImportDevice() 
{ 
    try 
    { 
    await AddDeviceClickExecute(); 
    } 
    catch (Exception ex) 
    { 
    ... 
    } 
} 

return _importDeviceCommand 
    ?? (_importDeviceCommand = new RelayCommand(ImportDevice, 
    () => _selectedCableType != null 
     && _selectedAddDevice != null 
     && _selectedPointNames != null 
     && _selectedPointNames.Any())); 
+0

Malheureusement, même cette modification n'attrape pas l'exception. Le code sort gentiment du bloc 'try/catch' et je rencontre le' TargetInvocationException' juste après le 'relayCommand' qui se termine par l'ajout de' AddDeviceClickExecute'. Pour information, cette exception ne se produit pas toujours. – ajr

+0

@ajr: Veuillez réduire au minimum la quantité de code nécessaire pour dupliquer le problème. –

+0

En fait, j'ai été capable de trouver la source d'exception, elle était liée aux capacités ICollectionView LiveFiltering. Je ne sais pas pourquoi c'est arrivé, mais je me suis remis à utiliser l'approche habituelle 'collection.Filter = FilterIfConnected;' et tout semble relativement bien pour le moment. – ajr