2

我在项目中使用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);
    }
}
4

1 回答 1

2

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

理想情况下,您会找到您正在使用await和丢失的地方ConfigureAwait(false)

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

一个快速的解决方法是包装 Rsync 代码,在Task.Run(() => ...).Wait();该代码中有效地清除此代码期间的同步上下文。因此,失踪ConfigureAwait(false)不再有影响。

这种修复通常是可以接受的。它有性能成本,因为它多消耗一个线程并且有一些同步成本。通常,这是无关紧要的。如果您使用一个随机的 ASP.NET 应用程序并将线程数加倍,那么这几乎是零影响的机会很高。从好的方面来说,修复显然是正确的并且易于维护。

于 2016-09-27T09:06:03.673 回答