我在一个项目中使用Librsync来计算文件的两个版本之间的差异,并将更改应用于旧文件。
在我的项目之外,我让它在一个简单的控制台应用程序中工作,该应用程序从两个不同的目录读取文件,对它们进行“修补”,并将其写到一个修补过的目录中。
代码示例-
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);
}
}发布于 2016-09-27 17:06:04
在评论中,我们发现这是“经典ASP.NET死锁”的一个实例。
理想情况下,您可以找到正在使用await但缺少ConfigureAwait(false)的地方。
我不认为这是Rsync库中的错误。如果情况允许,则不禁止在任务上调用Result。库被允许假设这不会死锁。它没有办法检查这是否是一个安全的操作,所以它只能这样做,并依赖调用者提供正确的对象。
一种快速的解决方法是将Rsync代码包装在Task.Run(() => ...).Wait();中,这将有效地清除此代码持续时间内的同步上下文。因此,丢失的ConfigureAwait(false)不再有任何影响。
这个修复通常是可以接受的。它有一个性能成本,因为它多消耗一个线程,并且有一些同步成本。通常,这是无关紧要的。如果你随机选取一个ASP.NET应用程序,并将线程数量加倍,那么这种影响几乎为零的可能性很高。从好的方面来看,修复显然是正确的,并且易于维护。
https://stackoverflow.com/questions/39614115
复制相似问题