2013-03-26 10 views
6

Json.net posiada funkcje async przekształcania obiektu do JSON jak:Json.net asynchroniczny przy zapisie do pliku

jsn = await JsonConvert.DeserializeObjectAsync<T> 

Ale gdy chcę writea obiektu do pliku json wydaje mi się lepiej wykonaj bezpośrednio przy użyciu strumienia plików.

Więc myślę, że powinno być coś takiego:

var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite); 

    using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0)) 
    { 
     using (StreamWriter sw = new StreamWriter(fileStream.AsStreamForWrite())) 
     { 
      using (JsonWriter jw = new JsonTextWriter(sw)) 
      { 
       jw.Formatting = Formatting.Indented; 

       JsonSerializer serializer = new JsonSerializer(); 
       serializer.Serialize(jw, obj); 
      } 
     } 

Ale na obiekcie JsonSerzializer nie mogę znaleźć metody async. Sądzę również, że operacje IO nie powinny być umieszczane we własnym wątku.

Jakie jest zalecane podejście?

Odpowiedz

9

Json.NET nie obsługuje tak naprawdę asynchronicznego de-/serializacji. Metody asynchroniczne na JsonConvert są tylko owijkami nad metodami synchronicznymi, które uruchamiają je na innym wątku (which is exactly what a library shouldn't do).

Myślę, że najlepszym rozwiązaniem byłoby uruchomienie kodu dostępu do pliku w innym wątku. To nie zapewni Ci pełnej korzyści z async (spowoduje to marnowanie wątku), ale nie zablokuje wątku interfejsu użytkownika.

+0

Dzięki za wskazanie, że obecnie. Zastanawiam się już, jak operacja łańcuchowa może być bez wątków asynchron. Przesyłanie strumieniowe może być wykonane jako asynchron. Być może byłaby to funkcja dla Json.net, ale oczywiście nie została jeszcze wprowadzona. Dziękuję za odpowiedź. –

+0

To byłoby proste zadanie do wykonania - tworzenie asynchronicznego rozwidlenia JSON.Net. Problem jednak polega na tym, że zajęłoby to dużo czasu - każdemu udało się zaoszczędzić około 80 godzin? Jeśli nie więcej? – Todd

4

Zobacz także ten kod, który wykorzystuje prawy asynchroniczny sposób (np. Nie tworzy wielkich tablic bajtowych, aby uniknąć alokacji pamięci LOH, nie będzie czekać na zakończenie operacji IO).

using (var file = File.Open(destination, FileMode.Create)) 
{ 
    using (var memoryStream = new MemoryStream()) 
    { 
     using (var writer = new StreamWriter(memoryStream)) 
     { 
      var serializer = JsonSerializer.CreateDefault(); 

      serializer.Serialize(writer, data); 

      await writer.FlushAsync().ConfigureAwait(false); 

      memoryStream.Seek(0, SeekOrigin.Begin); 

      await memoryStream.CopyToAsync(file).ConfigureAwait(false); 
     } 
    } 

    await file.FlushAsync().ConfigureAwait(false); 
} 

cały plik: https://github.com/imanushin/AsyncIOComparison/blob/0e2527d5c00c2465e8fd2617ed8bcb1abb529436/IntermediateData/FileNames.cs

+1

IMHO, ta odpowiedź jest lepsza niż zaakceptowana odpowiedź, biorąc pod uwagę, że zaakceptowana odpowiedź całkowicie zignorowała fakt, że użytkownik próbował wykonać IO i nie daje prawdziwego przykładu. –

Powiązane problemy