2016-08-29 3 views
0

나는 스트림에서 파생 된 클래스가 있고 해당 읽기/쓰기, 나는 데이터베이스에 충돌해야합니다. 나는 SQLDATA 객체의 * 비동기 방법을 사용하고 싶어하지만 물론이 같은 (내 생각)에 비동기 수정을 가지고 읽기의 서명을 변경하는 나를 원하는 :다른 비동기 메서드를 호출하는 사용자 정의 스트림 클래스

public async override Task <int> Read(byte[] buffer, int offset, int count) 

을 그리고하지 않습니다 실제 서명과 일치하므로 컴파일 오류 메시지가 표시됩니다. 어떻게 든이 스트림 내에서 * Async를 사용하여 어떻게 풀 수 있었는지, 아니면 그냥 동기로 두어야합니까?

나는 또한 내 클래스가 http://www.syntaxwarriors.com/2013/stream-varbinary-data-to-and-from-mssql-using-csharp/에서 가장 아이디어를 SQL Server의에와 VARBINARY (최대) 필드에서 데이터의 스트리밍을 가능하게한다 https://blogs.msdn.microsoft.com/pfxteam/2011/01/15/asynclazyt/

에서 스티븐 Toub의 AsyncLazy을 사용했다. 여기

은 (주석 비동기 비트) 코드의 흥미 비트이다 :

public class BinaryDataStream<T> : Stream 
{ 
    /* Async */Lazy<SqlDataReader> lazyReader; 
    SqlConnection connection; 
    SqlCommand firstUpdate; 
    SqlCommand otherUpdates; 
    long position; 

    public BinaryDataStream(DbContext context, string tableName, string keyName, string columnName, T keyValue) 
    { 
     connection = new SqlConnection(context.Database.GetDbConnection().ConnectionString); 

     lazyReader = new /* Async */Lazy<SqlDataReader>(/* async */() => 
     { 
      using (var cmd = new SqlCommand($"SELECT TOP 1 [{columnName}] FROM [dbo].[{tableName}] WHERE [{keyName}] = @id", connection)) 
      { 
       cmd.Parameters.AddWithValue("@id", keyValue); 
       /* await */ connection.Open/* Async */(); 

       var r = /* await */ cmd.ExecuteReader/* Async */(System.Data.CommandBehavior.SequentialAccess | System.Data.CommandBehavior.SingleResult | System.Data.CommandBehavior.SingleRow | System.Data.CommandBehavior.CloseConnection); 
       r.Read(); 

       return r; 
      } 
     }); 

     firstUpdate = new SqlCommand($"UPDATE [dbo].[{tableName}] SET [{columnName}] = @firstchunk WHERE [{keyName}] = @id", connection); 
     firstUpdate.Parameters.AddWithValue("@id", keyValue); 
     firstUpdate.Parameters.AddWithValue("@firstchunk", new byte[] { }); 

     otherUpdates = new SqlCommand($"UPDATE [dbo].[{tableName}] SET [{columnName}].WRITE(@chunk, NULL, @length) WHERE [{keyName}] = @id", connection); 
     otherUpdates.Parameters.AddWithValue("@id", keyValue); 
     otherUpdates.Parameters.AddWithValue("@length", 0); 
     otherUpdates.Parameters.AddWithValue("@chunk", new byte[] { }); 
    } 

    public /* async */ override /* Task< */int/* > */ Read(byte[] buffer, int offset, int count) 
    { 
     var reader = /* await */ lazyReader.Value; 
     var bytesRead = reader.GetBytes(0, position, buffer, offset, count); 
     position += bytesRead; 
     return (int)bytesRead; 
    } 

    public /* async */ override void Write(byte[] buffer, int offset, int count) 
    { 
     if (count == 0) return; 

     /* await */ connection.Open/* Async */(); 

     try 
     { 
      if (firstUpdate != null) 
      { 
       firstUpdate.Parameters[ "@firstchunk" ].Value = buffer; 
       /* await */ firstUpdate.ExecuteNonQuery/* Async */(); 
       firstUpdate = null; 
      } 
      else 
      { 

       var chunk = buffer; 
       if (count < buffer.Length) 
       { 
        chunk = new byte[ count ]; 
        Array.Copy(buffer, 0, chunk, 0, count); 
       } 

       otherUpdates.Parameters[ "@chunk" ].Value = chunk; 
       otherUpdates.Parameters[ "@length" ].Value = count; 
       /* await */ otherUpdates.ExecuteNonQuery/* Async */(); 
      } 
     } 
     finally 
     { 
      connection.Close(); 
     } 
    } 
} 
+1

'대기'또는 '결과'를 호출하면 교착 상태가 발생할 수 있습니다. 비동기 버전을 래핑하여 동기 변형을 구현하지 마십시오. 동기 버전의 경우 동기식으로 진행하십시오. (그리고 비동기를위한 비동기) 비동기 메서드에 대해서는 동기 래퍼를 노출해야합니까? (https://blogs.msdn.microsoft.com/pfxteam/2012/04/13/should-i-expose-synchronous- wrappers-for-asynchronous-methods /) –

+0

왜 비동기 메서드를 사용 하시겠습니까? –

+0

db 클래스의 * Async() 메서드를 사용하려는 이유를 묻는다면 ... '가정'이라고 가정했습니다. 모든 IO 물건, 나는 가능한 한 언제나'await * Async()'를 사용하는 것이 좋다고 생각했다 ?? – Terry

답변

2

Stream 클래스는 그 방법의 동기 및 비동기 버전을 모두 갖는다. 마찬가지로 실행중인 데이터베이스 작업은 해당 메서드의 동기 및 비동기 버전을 모두 표시합니다. 동기 구현을 사용하여 동기 메소드를 대체하고 비동기 구현으로 비동기 메소드를 대체하십시오.

+0

그래서 본질적으로 db 연산의 비동기 메서드를 사용하려면 호출자가 내 Stream 클래스의 비동기 메서드를 사용해야합니다. – Terry

+0

@Terry Correct. – Servy

+0

그 이유는 우리가'NotSupportedException'을 가지고있는 이유입니다. –

관련 문제