2013-04-16 10 views
7

Sto tentando di creare un'interfaccia di serializzazione (simile al protocollo NSCoding di Cocoa) in modo da ottenere una rapida rappresentazione binaria di una classe da inviare attraverso una rete o un archivio in un database. Tuttavia, alcuni casi (specialmente quelli relativi alla codifica delle immagini) hanno molti metodi solo asincroni che richiedono lo await ing. Tuttavia, se i byte non vengono scritti in ordine, ovviamente l'intera rappresentazione è corrotta. Devo assicurarmi che l'oggetto corrente abbia terminato la serializzazione prima di continuare con l'oggetto successivo. Ecco il ciclo principale di ciò che sto facendo.Come posso gestire un metodo di interfaccia che può essere o meno asincrono?

public async static Task<byte[]> Serialize(this IList<ISerializable> list) { 
     using (Archiver archiver = new Archiver()) { 
      archiver.Write(list.Count); 
      foreach (ISerializable value in list) { 
       await archiver.Write(value); 
      } 
      return archiver.Result; 
     } 
    } 

Archiver solo utilizza MemoryStream e BitmapWriter sotto il cofano per scrivere o valori che BinaryWriter può accettare direttamente o ISerializable oggetti, e poi sputa fuori il risultato come un array di byte. ISerializable è solo un'interfaccia con due metodi (Serialize e Deserialize). Entrambi restituiscono Task in modo che possano essere await ed. Il problema è quando ho un metodo di serializzazione che non ha componenti asincroni. Posso fare una delle due cose:

A) posso virare su async ai metodi di serializzazione di quella classe in ogni modo e mettere in su con l'avvertimento del compilatore dicendo che eseguirà in modo sincrono (non mi piace avere avvisi del compilatore).

B) Restituisce manualmente un'attività vuota alla fine del metodo (return Task.Run(() => {});). Tuttavia, questo aspetto e gli odori sono davvero strani.

Sia A che B sembrano funzionare senza problemi, ma ci sono problemi con questo approccio che potrei aver perso? Non sono a conoscenza di un serializzatore binario in Windows Runtime (ho incluso il tag solo per dissipare ogni confusione). Forse c'è un'opzione C che posso prendere in considerazione? In realtà non volevo rendere asincroni i metodi di serializzazione, ma per qualche motivo non era in attesa e stavo ottenendo un'eccezione di riferimento null provando a usare un oggetto creato con CreateAsync prima che fosse pronto.

EDIT Ho pensato a un'opzione C. Potrei semplicemente racchiudere l'intero metodo in una chiamata await Task.Run(...). Sarebbe normale?

+0

È possibile attendere Task.Delay (0), restituisce immediatamente. –

+0

@HansPassant Mi piace piuttosto questa soluzione ^^ – borrrden

+0

L'immagine sta elaborando una libreria di terze parti? Chiedo perché mi sembra che la codifica delle immagini (e la serializzazione in generale) non siano operazioni "asincrone" naturalmente. Detto questo, preferisco la soluzione di @ svick, che è come l'opzione B con meno overhead. –

risposta

4

Penso che la soluzione migliore qui, assumendo che si voglia eseguire il metodo in modo sincrono è di scriverlo normalmente, tranne che si restituirà un Task completato alla fine del metodo.

Per ottenere un Task completo con un valore specifico, è possibile utilizzare Task.FromResult().

Se si desidera un Task senza valore (vale a dire in realtà solo Task, non Task<TResult>), è possibile utilizzare per esempio Task.FromResult(true) (che è un Task<bool>) e implicitamente gettarlo ai Task.

+0

In che modo si confronta, nella tua mente, con il suggerimento nei commenti di 'Task.Delay (0)'? – borrrden

+0

@borrrden Praticamente, non penso che ci sia una differenza. Logicamente, penso che 'FromResult()' abbia senso, perché vuoi un 'Task' completato, non un ritardo. Inoltre, la versione sincrona di quel codice è 'Thread.Sleep (0)', che ha un significato speciale. Potrebbe essere fonte di confusione. – svick

Problemi correlati