2016-06-28 5 views
0

ReadAsync()実装(win 8.1のUnversalストアアプリケーション)に混乱させています。バッファをコピーしないで、IRandomAccessStreamを実装する

public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer targetBuffer, uint count, InputStreamOptions options) 

問題は、私がtargetBufferに書き込むとそのLength与えられた私の特定の実装要件を変更する方法を見つけることはできません。

私が持っているのは、いくつかのブロック暗号を持つ暗号化されたストリームです。私はIRandomAccessStreamでラップしたいので、xamlフレームワークコンポーネント(、暗号化された画像/ビデオをImageまたはMediaElementオブジェクトに渡すなど)で使用できます。クラスの中には、すべてのブロックに対して再利用するバイト配列があり、それを埋め込む暗号化ライブラリに渡し、チャンクサイズを報告します。

IRandomAccessStream.ReadAsync()が呼び出されたときに、何とか私のバイトをtargetBufferに入れ、Lengthを適切な値に設定する必要があります。これは管理していないようです。

私はこれを試してみました:

var stream = targetBuffer.AsStream(); 
while(count > 0) { 
    /* doing something to get next chunk of data decrypted */ 
    // byte[] chunk is the array used to hold decrypted data 
    // int chunkLength is the length of data (<= chunk.Length) 

    count -= chunkLength; 
    await stream.WriteAsync(chunk, 0, chunkLength); 
} 
return targetBuffer; 

そしてtargetBuffer.Lengthはゼロのまま、まだ私はそのコンテンツを印刷しようとした場合、データがあります!

Debug.WriteLine(targetBuffer.GetByte(0..N)); 

私は今(バイト配列バッファに加えて)メモリ・ストリームを使用する単純な実装を持って、そこにデータを収集しtargetBufferにそれから戻って読み出します。これはうまくいくが、悪く見える。管理されたストリームはbyte[]に書き込み、WinRTストリームはIBufferに書き込みます。私はメモリとパフォーマンスを浪費することはありません。

私は何か考えていただければ幸いです。

これは今のようです。私は、解読バッファーとしてバイト配列を使用し、プロキシーとしてサイズ変更可能なメモリー・ストリームを使用することになります。

public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer targetBuffer, uint count, InputStreamOptions options) 
{ 
    return AsyncInfo.Run<IBuffer, uint>(async (token, progress) => { 
    Transport.Seek(0); // Transport is InMemoryRandomAccessStream 
    var remaining = count; 
    while(remaining > 0) {  
     /* 
     ReadAsync() overload reads & decrypts data, 
     result length is <= remaining bytes, 
     deals with block cipher alignment and the like 
     */ 
     IBuffer chunk = await ReadAsync(remaining); 

     await Transport.WriteAsync(chunk); 
     remaining -= chunk.Length; 
    } 
    Transport.Seek(0); 
    // copy resulting bytes to target buffer 
    await Transport.ReadAsync(targetBuffer, count, InputStreamOptions.None); 
    return targetBuffer; 
    }); 
} 

UPDATE:私は7.9MBの暗号化された画像と上記溶液をテストしてみました。

var image = new BitmapImage(); 
await image.SetSourceAsync(myCustomStream); 
Img.Source = image; // Img is <Image> in xaml 

すべてがOKでそれまでは実行await Transport.ReadAsync(targetBuffer, count, InputStreamOptions.None);に到達する:そこ有効電話エミュレータをクラッシュメモリ消費急騰(300 + MBに33メガバイトの周りから)、(デスクトップバージョンは、画像を申し分示し、IはこのようImageインスタンスに供給しましたメモリはまったく同じです)。地獄はそこに行っているのですか?

2017年3月で解決

まず、私は何とか私はちょうどバッファにデータを書き込んだ後、直接Lengthを設定することができます実現しませんでした。第二に、私の場合(カスタムIRandomAccessStreamの実装がXAML Image要素のソースである)、何か間違っているとすれば、アプリはクラッシュしてログを残さず、エラーも表示しないので、何がうまくいかないのか分かりません。

これは、コードが今のように見えるものです:

System.Runtime.InteropServices.WindowsRuntimeを使用して
public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer targetBuffer, uint count, InputStreamOptions options) 
{ 
    return AsyncInfo.Run<IBuffer, uint>(async (token, progress) => { 
     var output = targetBuffer.AsStream(); 
     while (count > 0) { 
      // 
      // do all the decryption stuff and get decrypted data 
      // to a reusable buffer byte array 
      // 
      int bytes = Math.Min((int) count, BufferLength - BufferPosition); 
      output.Write(decrypted, bufferPosition, bytes); 
      targetBuffer.Length += (uint)bytes; 
      BufferPosition += bytes; 
      progress.Report((uint)bytes); 
      count -= (uint)bytes; 
     } 
    } 
    return targetBuffer; 
}); 
+0

どのようにあなたが 'targetBuffer'初期ましたか? 'targetBuffer.Length'はどのようにゼロになりますか?私は 'ReadAsync(...)'メソッドで 'targetBuffer'を使うと、パラメータ' uint count'の長さがあるはずです。 –

+0

私はtargetBufferをまったく作成していません。 'Image.SetSource(IRandomAccessStream)'や 'MediaElement.SetSource(IRandomAccessStream、" video/mp4 ")'を実行して独自のストリーム実装を渡すと 'targetBuffer.Length'が0の状態で' ReadAsync() 'が呼び出されます。バッファーROMにwinrtストリームを読み込むと、長さが正しく設定されます。 –

+0

winrtストリームからバッファに読み込むと、コードに示すように長さが適切に設定されます: 'Transport.ReadAsync(targetBuffer ...)'。 –

答えて

1

(your byte array).CopyTo(targetBuffer);

IBufferでのLengthプロパティは、セッター

次のコードは、あなたの中から選択するのCopyToのより多くのバリエーションを持っている

targetBuffer.Length = (your integer here)

完全に有効である持っています。この1を見て:

public static void CopyTo(this byte[] source, int sourceIndex, IBuffer destination, uint destinationIndex, int count);

+0

ああ。 :)私はちょうどバッファにデータを書き込んだ後に長さを設定することができたことを認識していませんでした。私は今何をしているかを示すために投稿を更新しました。ありがとう! –

関連する問題