我有这段代码来计算给定输入文件的MD5哈希值。
public static String ComputeMD5(String filename)
{
using (var md5 = MD5.Create())
{
try
{
using (var stream = File.OpenRead(filename))
{
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
}
}
catch (Exception)
{
// File is not accessible, return String.Empty
return String.Empty;
}
}
}
我在一个单独的线程中运行这个耗时的操作。对于非常大的文件,此操作可能需要几秒/分钟。我想要做的是能够从另一个线程停止操作,例如使用" Stop" GUI中的按钮。有什么建议吗?
答案 0 :(得分:1)
您可以阅读文件部分并将MD5.TransformBlock应用于每个阅读部分。 (注意,最后一部分应该用MD5.TransformFinalBlock来阅读)。 在处理每个块之间,您可以检查是否需要取消,您可以自由使用任何您喜欢的同步原语。
以下示例使用CancellationToken
:
using System;
using System.IO;
using System.Threading;
using System.Security.Cryptography;
namespace Stack
{
class Program
{
static void Main(string[] args)
{
using (var cancellationTokenSource = new CancellationTokenSource())
{
var thread = new Thread(() =>
{
try
{
var hash = CalcHash("D:/Image.iso", cancellationTokenSource.Token);
Console.WriteLine($"Done: hash is {BitConverter.ToString(hash)}");
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled :(");
}
});
// Start background thread
thread.Start();
Console.WriteLine("Working, press any key to exit");
Console.ReadLine();
cancellationTokenSource.Cancel();
}
Console.WriteLine("Finished");
Console.ReadLine();
}
static byte[] CalcHash(string path, CancellationToken ct)
{
using (var stream = File.OpenRead(path))
using (var md5 = MD5.Create())
{
const int blockSize = 1024 * 1024 * 4;
var buffer = new byte[blockSize];
long offset = 0;
while (true)
{
ct.ThrowIfCancellationRequested();
var read = stream.Read(buffer, 0, blockSize);
if (stream.Position == stream.Length)
{
md5.TransformFinalBlock(buffer, 0, read);
break;
}
offset += md5.TransformBlock(buffer, 0, buffer.Length, buffer, 0);
Console.WriteLine($"Processed {offset * 1.0 / 1024 / 1024} MB so far");
}
return md5.Hash;
}
}
}
}