2014-11-25 2 views
5

내가 가지고있는 다음과 같은 방법비동기 SHA256 해시

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); 
    } 
} 

비동기를 만들 수있는 방법이 있나요? 비동기 키워드를 기다리고 있지만 HashAlgorithm 클래스는이를위한 비동기 지원을 제공하지 않기를 바랍니다.

또 다른 방법

는 모든 로직을 캡슐화하는 것이었다 :

public static async string Sha256Hash(string input) { 
    return await Task.Run(() => { 
     //Hashing here... 
    }); 
} 

을하지만이 깨끗하지 않는 것 그리고 내가 비동기 작업을 수행 할 수있는 올바른 (또는 효율적으로) 방법입니다 있는지 확실하지 않습니다.

이 작업을 수행하려면 어떻게해야합니까?

+2

왜이 작업을 비동기 적으로 수행하려고합니까? –

+0

@CoryNelson 솔직히 모르겠습니다. 내가 비동기 적으로 또는 다른 스레드에서 실행되도록하여 코드를 최적화한다고 생각했습니다. 그러나 대답은 내 마음을 맑게했습니다. –

+0

@CoryNelson : 대용량 파일의 해시를 계산하는 동안 응답 성있는 UI를 유지하기 위해 비동기 적으로이 작업을 수행해야하는 상황에 직면했습니다. –

답변

6

작업은 본질적으로 동기 CPU 바운드 작업입니다. 네트워크 IO와 같은 것이 본질적으로 비동기적인 것은 아닙니다. 다른 스레드에서 일부 동기 CPU 바운드 작업을 실행하고 비동기 적으로 완료 될 때까지 기다리고 싶다면 Task.Run이 실제로 비동기 적으로 수행해야하는 작업이 충분히 오래 실행되었다고 가정 할 때 실제로이를 수행하는 데 적합한 도구입니다.

That said, there really isn't any reason to expose an asynchronous wrapper over your synchronous method. 일반적으로 메서드를 동 기적으로 노출하는 것이 더 좋으며 특정 호출자가 다른 스레드에서 비동기 적으로 실행해야하는 경우에는 Task.Run을 사용하여 특정 호출에 대한 필요성을 명시 적으로 나타낼 수 있습니다.

+2

그 때 당신의 충고를 따를 것입니다. 그리고 래퍼가 편리한지 여부를 호출자가 결정하게하십시오. –

1

(Task.Run을 사용하여)이 비동기 적으로 실행하는 오버 헤드는 아마도 동 기적으로 실행하는 것보다 높을 것입니다.

비동기 인터페이스는 CPU 바운드 작업이므로 사용할 수 없습니다. 당신이 지적한대로 (Task.Run을 사용하여) 비동기로 만들 수는 있지만 반대하는 것이 좋습니다.

1

다른 응답자의 말처럼 해시는 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 read; 

     // compute the hash on 8KiB blocks 
     while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) == buffer.Length) 
      algo.TransformBlock(buffer, 0, read, buffer, 0); 
     algo.TransformFinalBlock(buffer, 0, read); 

     // 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 다른 해시 알고리즘 메소드를 호출 할 수있다.

마찬가지로 몇 가지 수정 사항을 통해 케이스에 맞게 문자열을 해싱 할 수도 있습니다.