Параллельные хэш-вычисления с помощью нескольких TransformBlocks приводят к беспорядку.C#

Место общения программистов C#
Ответить
Anonymous
 Параллельные хэш-вычисления с помощью нескольких TransformBlocks приводят к беспорядку.

Сообщение Anonymous »

Я пытаюсь вычислить хеши для всего каталога, чтобы позже отслеживать изменения. Это относительно легко. Однако, если файлы большие, вычисления занимают слишком много времени, поэтому мне пришлось использовать многопоточность.

Благодаря узким местам ввода-вывода мне следует читать файл в одном потоке, но я могу вычислить хэш для этого файла в нескольких потоках с одновременным вызовом методов TransformBlock. Проблема в том, что результат каждого вычисления различен — поскольку все потоки обновляют один экземпляр хеш-алгоритма, они делают это хаотично.

Код: Выделить всё

  public delegate void CalculateHashDelegate(byte[] buffer);
private MD5 md5;
private long completed_threads_hash;
private object lock_for_hash = new object();

`private string getMd5Hash(string file_path)
{
string file_to_be_hashed = file_path;
byte[] hash;

try
{
CalculateHashDelegate CalculateHash = AsyncCalculateHash;
md5 = MD5.Create();

using (Stream input = File.OpenRead(file_to_be_hashed))
{
int buffer_size = 0x4096;
byte[] buffer = new byte[buffer_size];

long part_count = 0;
completed_threads_hash = 0;
int bytes_read;
while ((bytes_read = input.Read(buffer, 0, buffer.Length)) == buffer_size)
{
part_count++;
IAsyncResult ar_hash = CalculateHash.BeginInvoke(buffer, CalculateHashCallback, CalculateHash);
}

// Wait for completing all the threads
while (true)
{
lock (completed_threads_lock)
{
if (completed_threads_hash == part_count)
{
md5.TransformFinalBlock(buffer, 0, bytes_read);
break;
}
}
}

hash = md5.Hash;

}

StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("x2"));
}
md5.Clear();
return sb.ToString();
}
catch (Exception ex)
{
Console.WriteLine("An exception was encountered during hashing file {0}. {1}.", file_to_be_hashed, ex.Message);
return ex.Message;
}
}

public void AsyncCalculateHash(byte[] buffer)
{
lock (lock_for_hash)
{
md5.TransformBlock(buffer, 0, buffer.Length, null, 0);
}
}

private void CalculateHashCallback(IAsyncResult ar_hash)
{
try
{
CalculateHashDelegate CalculateHash = ar_hash.AsyncState as CalculateHashDelegate;
CalculateHash.EndInvoke(ar_hash);
}
catch (Exception ex)
{
Console.WriteLine("Callback exception: ", ex.Message);
}
finally
{
lock (completed_threads_lock)
{
completed_threads_hash++;
}
}
}
Есть ли способ организовать процесс хеширования? Я не могу использовать .Net новее 3.5 и такие классы, как BackroundWorker и ThreadPool. Или, может быть, есть другой метод параллельного вычисления хеша?

Подробнее здесь: https://stackoverflow.com/questions/331 ... a-disarray
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»