流.CopyTo与Librsync.PatchStream一起使用时会挂起

本文关键字:挂起 一起 CopyTo Librsync PatchStream | 更新日期: 2023-09-27 18:07:59

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

流.CopyTo与Librsync.PatchStream一起使用时会挂起

在评论中我们发现这是一个"经典ASP. js "的实例。净僵局"。

理想情况下,您会找到使用await而缺少ConfigureAwait(false)的地方。

我不相信这是一个bug在Rsync库。如果情况需要,在任务上调用Result是不被禁止的。允许库假定这不会死锁。它没有办法检查这是否是一个安全的操作,所以它必须执行它,并依赖调用者提供正确的对象。

快速修复是将Rsync代码包装在Task.Run(() => ...).Wait();中,这有效地清除了该代码期间的同步上下文。因此,缺失的ConfigureAwait(false)不再有任何影响。

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