2016-09-21 5 views
1

私はLibrsyncをプロジェクトで使用していますが、ファイルの2つのバージョンの違いを計算し、その変更を古いファイルに適用します。Stream.CopyTo Librsync.PatchStreamと一緒に使用するとハングします

私のプロジェクトの外では、2つの異なるディレクトリからファイルを読み込み、 "パッチ"してパッチを適用したディレクトリに書き出す単純なコンソールアプリケーションで作業しました。

コードサンプル - 私たちは、これは「古典的なASP.NETのデッドロック」のインスタンスであることが分かったコメントで

using (var deltaFile = new FileStream(tmpDeltaFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) 
{ 
    //myClient is the client of a WCF service I created 
    myClient.ComputeDelta(file.Id, signatureStream).CopyTo(deltaFile); 

    originalFile.Seek(0, SeekOrigin.Begin); 
    deltaFile.Seek(0, SeekOrigin.Begin); 
    var patchedStream = Librsync.ApplyDelta(originalFile, deltaFile); 

    using (var patchedFileStream = new FileStream(patchedFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) 
    { 
     //Code below just hangs. patchedStream pos = 0 and the length is the same as that of the new file. 
     patchedStream.CopyTo(patchedFileStream); 
    } 
} 
+0

デバッガを一時停止し、外部コードでハンドのコールスタックを送信します。 – usr

+0

ハングオン - 'public override int Read(byte []バッファ、intオフセット、intカウント) { return ReadAsync(buffer、offset、count) } 'PatchedStream.csで https://github.com/braddodson/librsync.net/blob/master/librsync.net/PatchedStream.cs – chickenbeef

+0

' .Result'の事は、古典的なASPのように見えます。 NETデッドロック。これは不明なコードのバグです。これをテストするには、 'Task.Run(()=> ...)。Wait();'に全体をラップします。 – usr

答えて

1

awaitを使用していて、ConfigureAwait(false)がない場所が理想的です。

これはRsyncライブラリのバグではないと思います。状況に応じて、タスク上でResultと呼ぶことは禁じられていません。ライブラリは、デッドロックしないと想定することができます。これは安全な操作かどうかをチェックする方法がないので、それを実行して呼び出し元に頼って正しいオブジェクトを提供する必要があります。

すぐに解決できるのは、にRsyncコードをラップすることです。このコードは、このコードの間、同期コンテキストを効果的に消去します。そのため、不足しているConfigureAwait(false)はもう影響を受けません。

この修正は通常受け入れられます。もう1つのスレッドを消費し、同期コストがかかるため、パフォーマンスコストが発生します。通常、これは重要ではありません。ランダムなASP.NETアプリケーションを使用し、スレッド数を2倍にすると、この影響がゼロになる可能性が高くなります。その上に修正は明らかに正確であり、維持しやすい。

関連する問題