0

I have wrote a simple service to serialize and deserialize classes with the default XmlSerializer. I wanted to do this async but when the XMlSerializer throws an exception inside the Task, it is not caught by the try/catch

public async Task<T> DeserializeAsync<T>(TextReader reader)
{
     try
     {
          return await Task.Run(() =>
          {
              var serializer = new XmlSerializer(typeof(T));
              var result = serializer.Deserialize(reader);
              return (T) result;
          });
     }
     catch (Exception e)
     {
          //Do something with exception
     }
}

I have one solution but it can't possibly be the solution to this problem:

public async Task<T> DeserializeAsync<T>(TextReader reader)
{

    Exception exception = null;
    var result = await Task.Run(
        () =>
        {
            try
            {
                return (T) new XmlSerializer(typeof(T)).Deserialize(reader);
            }
            catch (Exception e)
            {
                exception = e;
                return default(T);
            }
        });

    if (exception != null)
    {
        // handle exception
    }

    return result;
}

UPDATE: Code that reproduces the error:

using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

public class Program
{
    private static Serializer _serializer;

    static void Main(string[] args)
    {
        _serializer = new Serializer();
        Task.Factory.StartNew(ReadUsers);
        Console.ReadKey();
    }

    private static async Task ReadUsers()
    {
        var stream = new MemoryStream(Encoding.ASCII.GetBytes(""));
        try
        {
             var user = await _serializer.DeserializeAsync<User>(new StreamReader(stream));
            Console.WriteLine(user.Name);
        }
        catch (Exception e)
        {
            Console.WriteLine($"Caught exception: {e.Message}");
        }
    }
}

public class Serializer
{
    public async Task<T> DeserializeAsync<T>(TextReader reader)
        => await Task.Run(() => (T) new XmlSerializer(typeof(T)).Deserialize(reader));
}

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}
Wim
  • 378
  • 2
  • 6
  • 14
  • When you run a task it is a different process. So a exception handler will not capture an exception in a different process. – jdweng Oct 31 '18 at 09:17
  • But there has to be a proper way to catch those exceptions? – Wim Oct 31 '18 at 09:21
  • I can't reproduce your issue. [The exception _is_ caught](https://dotnetfiddle.net/yTtHWj) – default Oct 31 '18 at 09:41
  • [link](https://dotnetfiddle.net/qOwJvg): this is the code that reproduces the fault – Wim Oct 31 '18 at 10:08
  • 1
    avoid async void. If you change it to a `Task` and `.Wait()` for the result the exception will be caught. But since you never wait for the `GetTheUser()`the program will most likely exit before it handles the exception – default Oct 31 '18 at 10:18
  • Also, it would be awesome if you could add that mcve to your question instead! – default Oct 31 '18 at 10:33
  • You can read about why async void is bad here: https://stackoverflow.com/a/45449457/238902 – default Oct 31 '18 at 10:34
  • it is still not working... I posted the reproducing code above – Wim Oct 31 '18 at 11:50

0 Answers0