2010-06-10 3 views
1

메서드에 대한 비동기 호출과 관련하여 디자인 문제가 있습니다. 비동기 방법과 함께 만든C에서 다단계 비동기 메서드 호출 패턴

내가 다른 비동기 방법 : 즉

를 호출하는 다른 비동기 메서드를 호출 비동기 메서드를 호출하는 가장 좋은/좋은 패턴을 알고 싶습니다

, 내가 가지고있는 WCF 서비스 참조 다른 비동기 메서드에서 호출되는 다른 비동기 메서드에서 호출하려고합니다. 비 차단 GUI에 대한 모든 것.

감사합니다.

답변

3

유일한 목표는 블로킹 GUI가 아닌 경우 여러 단계가 필요하지 않습니다. 최상위 메소드가 백그라운드에서 실행되면 GUI가 해제됩니다. 여러 수준을 사용하면 추가 복잡성이 발생합니다.

낮은 수준의 메서드 async를 호출하는 다른 이유 (성능)가있을 수 있지만 그 방법은 다릅니다. 나중에 결과를 기다릴 필요가 있습니까?

그래서 여기서 '패턴'이 있다고 생각하지 않습니다.

+0

모두 완료되면 '최종 결과와 함께 랑데부'하는 데 약간의 노력이 필요할 수 있지만. – Brian

+1

아키텍처별로 여러 수준이 필요합니다. 그것은 관심사의 분리입니다. 이건 어때? – michajas

+1

@michajas : 여러 단계는 우려를 분리하는 것입니다. 비동기로 만들면 복잡성이 증가하고 우려가 생깁니다. (IAsyncResult) –

0

MonoRail 또는 MS MVC와 같은 MVC 프레임 워크에서 비동기 컨트롤러를 만들 때 여러 레벨을 갖는 것이 좋은 경우의 한 가지 예가 있습니다. 마지막으로 IO 블로킹 (예 : System.Data.SqlClient 또는 일부 소켓에서 SqlCommand 호출)은 IO 완료 포트에 IO 피연산자를 넣습니다. http://msdn.microsoft.com/library/aa365198, 관리되는/관리되지 않는 스레드의 퀀텀이 더 유용한 것으로 저장됩니다. .

IAsyncResult를 반환하는 클래스를 작성하면 공동 루틴을 구현하는 데 그리 멀지 않습니다. 코 루틴과 함께 비동기 프로그래밍을 사용할 수있는 방법에 대한 좋은 기사가 있습니다 : http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx.

Caliburn, WPF 프레임 워크는 기본적으로 공동 루틴을 지원합니다. .Net 4와 함께 출시 된 작업 병렬 라이브러리는 IAsyncResult 인터페이스를 제공합니다. [3.5에 있다면 자신 만의 구현을 만들어야 할 수도 있습니다. 인터페이스를 구현하는 것만으로도 간단합니다.] 공동 루틴은 컴파일러를 사용하여 IEnumerable을 다시 작성하여 IAsyncResults를 할 일의 스택 ("async manager"에서 보여지는 것처럼).

F # async (down-voted 대답과 유사)는 비동기 요청의 상태를 Begin * 메서드에서 End * 메서드로 이동하기 위해 모나드를 사용합니다 (CLR에서 모나드로 사용). 컴파일러는 이것을 모두 중첩 된 람다 식/SelectMany로 만듭니다.

0

최근 데이터를 검색하기 위해 백엔드 웹 서비스를 호출하는 ADFS 특성 저장소 구현을 개발했습니다. 나는 공장을 따라 원 - 오히려 각 통화에 대한 클라이언트를 다시보다> 클라이언트 접근 방식을, 그래서 아래의 간단한 코드 샘플에 도시 된 바와 같이 나는 2 수준의 비동기 호출에서 결국이 따를 수있는 좋은 패턴 인 경우 궁금

public class IMyAttributeStore : IAttributeStore 
{ 
    ChannelFactory<IMyBackendInterface> factory; 
    public IMyAttributeStore() 
    { 
    } 

    public IAsyncResult BeginExecuteQuery(string query, string[] parameters, AsyncCallback callback, object state) 
    { 
     AsyncResult queryResult = new TypedAsyncResult<string[][]>(callback, state); 
     var client = factory.CreateChannel(); 
     CallState cs = new CallState(client, queryResult); 

     Request rq = new Request(); 

     client.BeginGetUserRoles(rq, new AsyncCallback(AsyncCallCallback), cs); 

     return cs.result; 
    } 

    public string[][] EndExecuteQuery(IAsyncResult result) 
    { 
     return TypedAsyncResult<string[][]>.End(result); 
    } 

    // Initialize state here. 
    public void Initialize(Dictionary<string, string> config) 
    { 
     var endpoint = config["endpointConfigurationName"]; 
     factory = new ChannelFactory<IMyBackendInterface>(endpoint); 
    } 

    void AsyncCallCallback(IAsyncResult result) 
    { 
     CallState cs = (CallState)result.AsyncState; 

     Response data = cs.client.EndGetUserRoles(result); 
     List<string[]> claimData = new List<string[]>(); 
     foreach (var val in data.Values) 
      claimData.Add(new string[1] { val }); 
     string[][] retVal = claimData.ToArray(); 

     TypedAsyncResult<string[][]> queryResult = (TypedAsyncResult<string[][]>)cs.result; 
     queryResult.Complete(retVal, false); 
    } 
} 

class CallState 
{ 
    public IMyBackendInterface client; 
    public AsyncResult result; 

    public CallState(IMyBackendInterface c, AsyncResult r) 
    { 
     client = c; 
     result = r; 
    } 
} 

그 사이에 누군가가 더 좋은 사람을 찾았습니까?