を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;
});
どのようにあなたが 'targetBuffer'初期ましたか? 'targetBuffer.Length'はどのようにゼロになりますか?私は 'ReadAsync(...)'メソッドで 'targetBuffer'を使うと、パラメータ' uint count'の長さがあるはずです。 –
私はtargetBufferをまったく作成していません。 'Image.SetSource(IRandomAccessStream)'や 'MediaElement.SetSource(IRandomAccessStream、" video/mp4 ")'を実行して独自のストリーム実装を渡すと 'targetBuffer.Length'が0の状態で' ReadAsync() 'が呼び出されます。バッファーROMにwinrtストリームを読み込むと、長さが正しく設定されます。 –
winrtストリームからバッファに読み込むと、コードに示すように長さが適切に設定されます: 'Transport.ReadAsync(targetBuffer ...)'。 –