[英]Asynchronous SHA256 Hashing
我有以下方法:
public static string Sha256Hash(string input) {
if(String.IsNullOrEmpty(input)) return String.Empty;
using(HashAlgorithm algorithm = new SHA256CryptoServiceProvider()) {
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = algorithm.ComputeHash(inputBytes);
return BitConverter.ToString(hashBytes).Replace("-", String.Empty);
}
}
有没有办法让它异步? 我希望使用async和await关键字,但HashAlgorithm
类不为此提供任何异步支持。
另一种方法是将所有逻辑封装在一个:
public static async string Sha256Hash(string input) {
return await Task.Run(() => {
//Hashing here...
});
}
但这似乎并不干净,我不确定这是否是异步执行操作的正确(或有效)方法。
我能做些什么来实现这一目标?
正如其他回答者所说,散列是一种受 CPU 限制的活动,因此它没有您可以调用的异步方法。 但是,您可以通过异步地逐块读取文件,然后对从文件中读取的字节进行哈希处理来使哈希方法异步。 散列将同步完成,但读取将是异步的,因此您的整个方法将是异步的。
这是用于实现我刚刚描述的目的的示例代码。
public static async Threading.Tasks.Task<string> GetHashAsync<T>(this Stream stream)
where T : HashAlgorithm, new()
{
StringBuilder sb;
using (var algo = new T())
{
var buffer = new byte[8192];
int bytesRead;
// compute the hash on 8KiB blocks
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
algo.TransformBlock(buffer, 0, bytesRead, buffer, 0);
algo.TransformFinalBlock(buffer, 0, bytesRead);
// build the hash string
sb = new StringBuilder(algo.HashSize / 4);
foreach (var b in algo.Hash)
sb.AppendFormat("{0:x2}", b);
}
return sb?.ToString();
}
该函数可以这样调用
using (var stream = System.IO.File.OpenRead(@"C:\path\to\file.txt"))
string sha256 = await stream.GetHashAsync<SHA256CryptoServiceProvider>();
当然,您也可以使用其他哈希算法(例如SHA1CryptoServiceProvider
或SHA512CryptoServiceProvider
作为泛型类型参数调用该方法。
同样,通过一些修改,您还可以根据您的情况对字符串进行哈希处理。
您正在做的工作本质上是同步的 CPU 绑定工作。 它不像网络 IO 那样本质上是异步的。 如果您想在另一个线程中运行一些同步 CPU 绑定的工作并异步等待它完成,那么Task.Run
确实是完成该任务的合适工具,假设该操作运行时间足够长,需要异步执行它。
也就是说,确实没有任何理由在同步方法上公开异步包装器。 通常只同步公开方法更有意义,如果特定调用者需要它在另一个线程中异步运行,他们可以使用Task.Run
显式指示需要该特定调用。
异步运行(使用 Task.Run)的开销可能会高于同步运行。
异步接口不可用,因为它是 CPU 绑定操作。 正如您所指出的,您可以使其异步(使用 Task.Run),但我建议您不要这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.