2013-04-16 12 views
7

私はクラスのクイックバイナリ表現をネットワーク経由で送信したり、データベースに保存したりできるように、シリアル化インターフェイス(CocoaのNSCodingプロトコルに似ています)を作成しようとしています。しかし、いくつかの場合(特にイメージエンコーディングを含む)には、awaitを必要とする多くの非同期メソッドがあります。しかし、バイトが順番に書き込まれなければ、もちろん全体の表現が壊れてしまいます。次のオブジェクトに進む前に、現在のオブジェクトがシリアライズを完了していることを確認する必要があります。ここに私がやっていることのメインループがあります。非同期であっても非同期であってもよいインターフェイスメソッドはどのように処理できますか?

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だけBinaryWriter直接受け入れるか、ISerializableオブジェクトができるいずれかの値を書き込むためにフードの下MemoryStreamBitmapWriterを使用し、その後、バイト配列として結果を出してくれる。 ISerializableは、2つのメソッド(SerializeDeserialize)を持つ単なるインターフェイスです。両方ともTaskを返すので、awaitにすることができます。問題は、非同期コンポーネントを持たないシリアライズメソッドがある場合です。

A)とにかく、そのクラスのシリアライゼーションメソッドをタックして、コンパイラの警告を出して、同期的に実行することを警告します(私はコンパイラの警告を受けたくありません)。

B)メソッドの最後に手動で空のタスクを返します(return Task.Run(() => {});)。しかし、これは本当に奇妙に見えます。

AとBの両方が問題なく実行されているように見えますが、このアプローチには問題がありますか?私はWindowsランタイムでバイナリシリアライザを認識していません(混乱を避けるためにタグを付けました)。おそらく、私が考えることができるオプションCがありますか?実際には、シリアライズメソッドを非同期にしたくないのですが、何らかの理由でtask.Wait()が待機していなかったので、準備が整う前にヌル参照例外が発生しました。CreateAsyncで作成したオブジェクトを使用しようとしました。

EDIT私はオプションCを考えました。await Task.Run(...)呼び出しでメソッド全体をラップすることができます。これは正常でしょうか?

+0

タスクを待つことができます。遅延(0)、すぐに戻ります。 –

+0

@HansPassant私はその解決策が好きです^^ – borrrden

+0

画像処理はサードパーティのライブラリですか?イメージエンコーディング(および一般的なシリアライゼーション)は自然に非同期操作ではないように思えるからです。つまり、私は@ svickのソリューションを好んでいます。これは、オプションBのようなオーバーヘッドは少ないです。 –

答えて

4

ここでは、メソッドを同期して実行することを前提としていますが、メソッドの最後に完了したTaskを返す以外は、通常の方法で記述することをお勧めします。

Taskを特定の値で取得するには、Task.FromResult()を使用できます。

あなたは(すなわち、実際にはTask、ないTask<TResult>)値なしでTaskをしたい場合は、(Task<bool>ある)例Task.FromResult(true)のために使用し、暗黙的にTaskにキャストすることができます。

+0

これは、あなたの心の中で、 'Task.Delay(0)'のコメントの提案とどのように比較されますか? – borrrden

+0

@borrrden実際には、私は違いがあるとは思わない。論理的には、私は 'FromResult()'が理にかなっていると思います。なぜなら、あなたが完了した 'Task'を望むからであり、遅延ではありません。また、そのコードの同期バージョンは 'Thread.Sleep(0)'です。これは特別な意味を持ちます。それは混乱するかもしれません。 – svick

関連する問題