2009-06-19 4 views
4

Event-based Asynchronous method pattern을 사용하여 구현 된 메소드가 있습니다. 또한 해당 메서드의 동기 버전을 제공하려고하지만 다시 작성하지는 마십시오. Silverlight에서 WCF를 호출해야하기 때문에 비동기 버전이 기본 메서드 여야합니다.비동기 메서드를 동기 메서드로 변환하는이 메서드가 올바른 것입니까?

나는 동기 하나에 이벤트 기반 비동기 호출로 변환하기 위해 다음과 같은 일반적인 방법을 마련했습니다

:

void ConnectAsync(string address, 
    string userName, 
    string password, 
    EventHandler<ConnectCompletedEventArgs> completionCallback) 

I :이 비동기 방법을 그래서 만약

Func<TArg1, TArg2, TArg3, TEventArgs> 
    CreateSynchronousMethodFromAsync<TArg1, TArg2, TArg3, TEventArgs>(
     Action<TArg1, TArg2, TArg3, EventHandler<TEventArgs>> asyncMethod) 
     where TEventArgs : AsyncCompletedEventArgs 
    { 
     Func<TArg1, TArg2, TArg3, TEventArgs> syncMethod = (arg1, arg2, arg3) => 
     { 
      TEventArgs eventArgs = null; 

      using (var waitHandle = new ManualResetEvent(false)) 
      { 
       asyncMethod(arg1, arg2, arg3, (sender, e) => 
              { 
               eventArgs = e; 
               waitHandle.Set(); 
              }); 

       waitHandle.WaitOne(); 

       return eventArgs; 
      } 
     }; 

     return syncMethod; 
    } 

을 이 같은 동기 호출로 변환 할 수 있습니다

public void Connect(string address, string userName, string password) 
{ 
    Func<string, string, string, ConnectCompletedEventArgs> connect = 
     CreateSynchronousMethodFromAsync<string, string, string, ConnectCompletedEventArgs>(ConnectAsync); 

    var connectResult = connect(address, userName, password); 

    if (connectResult.Error != null) 
    { 
     throw connectResult.Error; 
    } 
} 

내 관심사는 우리에 대해입니다 e를 닫음에서 캡처 한 eventArgs 변수의 값으로 설정합니다. 하나의 스레드에서 설정되고 다른 스레드에서 액세스됩니다. ManualResetEvent를 사용하여 이벤트가 신호를 받으면 올바른 값을 읽도록 보장합니까? 아니면 다른 작업을해야합니까?

글쎄, 여기에 예외 처리에 대해 언급하고 싶을 수도 있습니다. 내 계획은 비동기 메서드가 ConnectionException 또는 그와 비슷한 것으로 스택 아래쪽에서 발생하는 예외를 래핑하므로 내 생각에 예외를 다시 throw하는 것이이 경우 정확하다는 것입니다.

답변

2

참조한 페이지에서 논의 된 ASync 패턴을 기반으로하면 비동기 호출을 래핑하는 데 아주 좋은 시도입니다.

그러나 주저하게 만드는 것은 방법 이름 'BeginConnect'입니다. 일부 .NET 클래스는 'EndXxx'쌍이 비동기 호출을 처리하기 위해 일반적으로 이 필요하고 콜백 처리기에서 'EndXxx'호출이 호출되도록 지정합니다. 이는 스키마가 만족하지 않는 것입니다 에 대한.

랩핑하는 호출이 링크 된 페이지에서 논의 된 패턴을 실제로 따르는 경우, 랩핑하는 호출이 두 번째 종류 중 하나 인 경우 작동하지 않아야합니다.

+0

내 코드는 이벤트 기반 비동기 메서드 패턴을 따르는 메서드에서만 사용하도록 설계되었습니다. 내부 메서드 인 BeginConnect는 시작/끝 호출을 줄 바꿈 처리합니다. –

+0

'throw connectionResult.Error'대신 원래 예외의 스택 추적이 유지되도록 내부 예외로 새 예외로 래핑 할 수 있습니다. – jerryjvl

+2

@Sam : 링크 된 기사에서 규칙을 기반으로 메서드의 이름을 지정하고 혼란을 피하기 위해 'ConnectAsync'를 대신 사용하는 것이 좋습니다. – jerryjvl