2017-03-23 3 views
0

Dans mon application WPF, j'ai une classe qui sérialise et désérialise un objet donné depuis et vers JSON. Si j'appelle la méthode de désérialisation à partir du thread de l'interface utilisateur, cela fonctionne correctement. Cependant, je voudrais que cela fonctionne en arrière-plan, et chaque fois que c'est sur un autre thread je reçois une erreur "Exception a été levée par la cible d'une invocation".DataContractJsonSerializer échoue sur n'importe quel thread autre que le thread de l'interface utilisateur

Ceci est la méthode de désérialisation

public T ReadConfig<T>(string name) 
    { 
     InitializeFileSystem(); 
     var ConfigPath = KnownFolders.GetPath(KnownFolder.Documents) + @"\Abc\Config\"; 
     T returnObject = default(T); 
     if (string.IsNullOrEmpty(name)) return default(T); 
     var exists = File.Exists(ConfigPath + name + ".json"); 
     if (!exists) return returnObject; 
     var serializer = new DataContractJsonSerializer(typeof(T)); 
     StreamReader reader = new StreamReader(ConfigPath + name + ".json"); 

     returnObject = (T)serializer.ReadObject(reader.BaseStream); 

     reader.Close(); 
     return returnObject; 
    } 

Sur un fil autre que l'interface utilisateur, il échoue à .ReadObect (reader.BaseStream)

est inférieure à la où la méthode est appelée (App.xaml .cs)

/// <summary> 
    /// Override Application "Entry Point" 
    /// </summary> 
    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 

     InitializeModel(); 
     //Task.Run(() => { InitializeModel(); }); 
     //ThreadPool.QueueUserWorkItem(InitializeModel); 
    } 

    private void InitializeModel(object state = null) 
    { 
     var fileSystem = new FileSystem(); 
     CurrentIndex = fileSystem.ReadConfig<IndexModel>("Index"); 
     CurrentIndex.Start(); 
    } 

Compilé comme indiqué ci-dessus, il fonctionne très bien, si je commente l'appel à InitializeModel() et utiliser à la place une nouvelle tâche ou un élément de travail tous l'enfer se déchaîne. Je suis au bout du compte, il n'est pas possible d'utiliser le thread de l'interface utilisateur, donc toute aide pour résoudre ce problème serait grandement appréciée.

+1

Que fait InitializeFileSystem? –

+0

Quelle est la sortie 'ToString()' complète de l'exception, y compris le type d'exception, message, traceback, ** et l'exception interne **? Si le message indique, * Exception a été levée par la cible d'une invocation * alors le 'InnerException' devrait avoir les détails nécessaires. Peut-être que le thread principal et le thread d'arrière-plan sont en concurrence pour l'accès au même fichier? – dbc

+0

Tout ce qu'il fait est de s'assurer que les dossiers existent et les créer si le ne - dans ce cas "Documents \ Abc \ Config \". Il crée également un objet index sérialisé avec des valeurs par défaut et l'enregistre sous le nom Index.json, ce qui est en cours de récupération la méthode ReadConfig – Michael

Répondre

0

J'ai trouvé le problème. Comme il était sans rapport avec le code dans la question, voici le code incriminé:

Mon IndexModel (la classe étant désérialisée) mis en œuvre l'interface INotifyPropertyChanged et a la méthode suivante

private void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

C'était appelé quand l'objet a été désérialisé (oops), commentant le problème résolu pour l'instant.