0

In my WPF application, I have class that serializes and deserializes a given object to and from JSON. If I call the deserialization method from the UI thread it works fine. However I would like it to work in the background, and whenever it's on another thread i get an "Exception has been thrown by the target of an invocation" error.

This is the deserialization method

    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;
    }

On any thread other than the UI, it fails at .ReadObect(reader.BaseStream)

Below is the where the method gets called (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();
    }

Compiled as shown above it works fine, however if i comment out the call to InitializeModel() and instead use a new task or work item all hell breaks loose.

I'm at the end of my tether here, running this on the UI thread is not an option so any help getting this resolved would be greatly appreciated.

dbc
  • 104,963
  • 20
  • 228
  • 340
Michael
  • 177
  • 3
  • 11
  • 1
    what does InitializeFileSystem do? – d.moncada Mar 23 '17 at 03:09
  • What is the full `ToString()` output of the exception including the exception type, message, traceback, **and inner exception**? If the message states, *Exception has been thrown by the target of an invocation* then the `InnerException` should have the necessary details. Possibly the main thread and background thread are both competing for access to the same file? – dbc Mar 23 '17 at 03:14
  • All it does is make sure the folders exist and create them if the don't - in this case "Documents\Abc\Config\". It also creates a serialized index object with default values and saves it as Index.json, which is what is being retrieved the the ReadConfig method – Michael Mar 23 '17 at 03:17
  • All i get is System.Reflection.TargetInvocationException was unhandled Message: An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in PresentationFramework.dll Additional information: Exception has been thrown by the target of an invocation. It has the PDB not loaded screen i can't catch the error – Michael Mar 23 '17 at 03:19

1 Answers1

0

I found the problem. As it was unrelated the code in the question, here is the offending code:

My IndexModel (the class being deserialized) implemented the INotifyPropertyChanged interface and had the following method

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

This was being being called when the object was deserialized (oops), commenting it out solved the issue for now.

Michael
  • 177
  • 3
  • 11