为什么SHA1.ComputeHash在很multithreading的高负载下失败?

我看到我维护的一些代码存在问题。 下面的代码有一个private static SHA1成员(这是一个IDisposable但因为它是static ,它永远不应该最终确定)。 但是,在压力下,此代码会抛出一个exception,表明它已被关闭:

 Caught exception. Safe handle has been closed" Stack trace: Call stack where exception was thrown at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success) at System.Security.Cryptography.Utils.HashData(SafeHashHandle hHash, Byte[] data, Int32 cbData, Int32 ibStart, Int32 cbSize) at System.Security.Cryptography.Utils.HashData(SafeHashHandle hHash, Byte[] data, Int32 ibStart, Int32 cbSize) at System.Security.Cryptography.HashAlgorithm.ComputeHash(Byte[] buffer) 

有问题的代码是:

 internal class TokenCache { private static SHA1 _sha1 = SHA1.Create(); private string ComputeHash(string password) { byte[] passwordBytes = UTF8Encoding.UTF8.GetBytes(password); return UTF8Encoding.UTF8.GetString(_sha1.ComputeHash(passwordBytes)); } 

我的问题显然是什么可能导致这个问题。 对SHA1.Create的调用是否可以SHA1.Create失败(有多少加密资源可用)? 这可能是因为appdomain失败了吗?

还有其他理论吗?

根据HashAlgorithm基类的文档

此类型的任何公共静态(在Visual Basic中为Shared)成员都是线程安全的。 任何实例成员都不保证是线程安全的。

您不应该在不同线程尝试并在同一实例上同时调用ComputeHash线程之间共享这些类。

编辑这是导致您的错误的原因。 由于多个线程在同一个哈希算法实例上调用ComputeHash,下面的压力测试会产生各种错误。 你的错误就是其中之一。

具体来说,我在压力测试中看到了以下错误:

  • System.Security.Cryptography.CryptographicException:哈希在指定状态下无效。
  • System.ObjectDisposedException:已关闭安全句柄

压力测试代码示例:

 const int threadCount = 2; var sha1 = SHA1.Create(); var b = new Barrier(threadCount); Action start = () => { b.SignalAndWait(); for (int i = 0; i < 10000; i++) { var pwd = Guid.NewGuid().ToString(); var bytes = Encoding.UTF8.GetBytes(pwd); sha1.ComputeHash(bytes); } }; var threads = Enumerable.Range(0, threadCount) .Select(_ => new ThreadStart(start)) .Select(x => new Thread(x)) .ToList(); foreach (var t in threads) t.Start(); foreach (var t in threads) t.Join();