Stream.CopyTo与Librsync.PatchStream一起使用时挂起

时间:2016-09-21 10:33:55

标签: c# .net stream filestream librsync

我在项目中使用Librsync来计算文件的两个版本之间的差异,并将更改应用于旧文件。

在我的项目之外,我让它在一个简单的控制台应用程序中工作,该应用程序从2个不同的目录中读取文件,“修补”它们并将其写入修补目录。

代码示例 -

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);
    }
}

1 个答案:

答案 0 :(得分:2)

在评论中我们发现这是"经典ASP.NET死锁的一个实例"。

理想情况下,您可以找到使用=RANK.AV(B1,ARRAY.JOIN(A1:A8,B1))的地方但缺少await

我不认为这是Rsync库中的错误。如果情况需要,不禁止在任务上调用ConfigureAwait(false)。允许库假设这不会死锁。它无法检查这是否是一个安全的操作,所以它必须这样做,并依靠调用者提供正确的对象。

快速解决方法是将Rsync代码包装在Result中,以便在此代码的持续时间内有效地清除同步上下文。因此,失踪的Task.Run(() => ...).Wait();不再有任何影响。

此修复通常是可以接受的。它具有性能成本,因为它消耗了一个以上的线程并且具有一些同步成本。通常,这是无关紧要的。如果你使用一个随机的ASP.NET应用程序并将线程数增加一倍,那么这几乎没有影响。在好的方面,修复显然是正确的,易于维护。