2010-02-07 3 views
5

저는 최근에 제가 다룰 수있는 모든 것을 배우려고 눈물을 흘 렸습니다 .Net Multithreading. (그것에 익숙해 지지만 여전히 배워야 할 것이 많다고 생각합니다.) 지금 내가 일반적이로 알려져 APM (비동기 프로그래밍 모델)에 초점을 해요 :비동기 프로그래밍 모델을 구현하는 좋은 방법입니까?

//non async method 
public int DoSomeWork(int arg) 
{ 
    //do something and return result 
} 

//async version 
public IAsyncResult BeginDoSomeWork(int arg, AsyncCallback callback, object @object) 
{ 

} 

public int EndDoSomeWork(IAsyncResult result) 
{ 

} 

를 자, 내가 어떤 라이브러리를 쓰고 있어요 가정 해 봅시다, 내가 소비하는 사람이라면이 기능을 노출 할 내 API,이 패턴을 구현하는 방법에 대해 생각했다. IAsyncResult 인터페이스를 구현하는 것도 가능하지만 상당히 복잡해 보입니다. 대리자를 사용하는 것이 수용 가능한 해결책이라면 제 질문입니다. 그것이 의미하는 바는 다음과 같습니다.

public class MyClass 
{ 
    private Func<int, int> func; 

    //non async method 
    public int DoSomeWork(int arg) 
    { 
     //do something and return result 
    } 

    //async version 
    public IAsyncResult BeginDoSomeWork(int arg, AsyncCallback callback, object @object) 
    { 
     this.func = new Func<int, int>(DoSomeWork); 
     var asyncResult = this.func.BeginInvoke(arg,callback,object); 
     return asyncResult; 
    } 

    public int EndDoSomeWork(IAsyncResult result) 
    { 
     return this.func.EndInvoke(result); 
    } 
} 

기본적으로 모든 대리인은 BeginXxx 및 EndXxx 기능이 포함되어 있습니다. 이를 활용하고 IAsyncResult를 노출하는 것이 좋을까요? 아니면 내가 생각하지 않은 무언가가 잘못되었습니다.

답변

1

나는 이것이 APM을 구현하는 좋은 방법이라고 생각하지만, 인스턴스 당 두 개 이상의 비동기 호출에 오류가 발생한다고 생각합니다.

대리인 사용을 외부화하지 않는 이유는 무엇입니까?

내 말은 당신이 당신의 메소드를 호출 사람을 당신의 클래스의 실제 로직을 넣어,하지만 할 경우보다 수행입니다 :

MyClass c = new MyClass(); 
Func<int, int> f = c.DoSomeWork; 
IAsyncResult ar1 = f.BeginInvoke(1, null, null); 
IAsyncResult ar2 = f.BeginInvoke(2, null, null); 
//... 

가 나는도를 구현되지 옹호하고있는 무슨 생각 APM을 직접 사용하는 것은 아니지만 대리자에 내장 된 APM을 사용하는 방법에 전화하는 사람들에게 권장하면됩니다.

0

IMHO, 귀하의 비동기 메서드는 어떤 값도 추가하지 않는다고 생각합니다. 따라서 클라이언트가 비동기 적으로 메서드를 호출할지 여부를 결정하게하십시오.

+0

예일뿐입니다. 실제 구현을 무시하고 (어리석게도 무의미한 것처럼 보임), 위임자를 사용하는 것에 대해 묻습니다. IAsyncResult입니다. – BFree

+0

동기식 버전과 비동기식 버전이 모두 제공되기 때문에 클라이언트는 여전히 해당 결정을 내립니다. OP는 선택된 방법이 APM을 구현하는 좋은 방법인지 아닌지에 대해 더 우려하고 있습니다. – Crippledsmurf

+0

@BFree, i c now. – Benny

0

다른 운동이 없다면 매우 효과적인 운동이라고 생각합니다. 나도 비동기적인 'delegate'핸들러를 만들고있다. 유연성을 높이면 비동기 모델에 대해 많은 것을 배울 수 있습니다.

나는이 SO question에 Linq 운동이 포함되어 있음을 알고 있습니다. 그러나 표현식 트리를 사용하여 좀 더 견고하게 만들 수 있습니다. 나는 아직 주제에 대해 잠수하고 구체적인 정보를 제공하지 못했습니다.

다음은 비동기 메서드를 게시 할 때 사용한 예전 코드 샘플입니다. 이것은 이며 학습을 반영하고 약간의 흥미로운 구현을 시도한입니다. 그게 가치있는 걸로 받아 들여라. 그러나 그것은 약간의 아이디어로 당신을 도울지도 모른다 :

public delegate void delVoidMethod(params object[] args); 

/// <summary> 
/// Publishes an asynchronous method to the delegate collection. 
/// </summary> 
/// <param name="methodOwner">Target object owning the delegated method.</param> 
/// <param name="method">The delegated method.</param> 
/// <param name="callback">The method designated as a callback delegate.</param> 
/// <param name="ptr">The delegated method's runtime handle.</param> 
/// <returns>True if publishing was successful.</returns> 
public bool PublishAsyncMethod(object target , MethodInfo method , 
    MethodInfo callback , out IntPtr ptr) 
{ 
    try 
    { 
     ptr = method.MethodHandle.Value; 

     delVoidMethod dMethod = (delVoidMethod)Delegate.CreateDelegate 
      (typeof(delVoidMethod) , target , method); 
     AsyncCallback callBack = (AsyncCallback)Delegate.CreateDelegate 
      (typeof(AsyncCallback) , target , callback); 

     handlers[ptr] = new DelegateStruct(dMethod , callBack); 

     Logger.WriteLine("Delegate : {0}.{1} -> {2}.{3} published." , 
      method.DeclaringType.Name , method.Name , 
      callback.DeclaringType.Name , callback.Name); 
     return true; 
    } 
    catch (ArgumentException ArgEx) 
    { 
     Logger.Write(DH_ERROR , ERR_MSG , 
      ArgEx.Source , ArgEx.InnerException , ArgEx.Message); 
    } 
    catch (MissingMethodException BadMethEx) 
    { 
     Logger.Write(DH_ERROR , ERR_MSG , 
      BadMethEx.Source , BadMethEx.InnerException , BadMethEx.Message); 
    } 
    catch (MethodAccessException MethAccEx) 
    { 
     Logger.Write(DH_ERROR , ERR_MSG , 
      MethAccEx.Source , MethAccEx.InnerException , MethAccEx.Message); 
    } 

    ptr = IntPtr.Zero; 

    return false; 
} 
0

나는 그다지 틀리게 아무것도하지 않는다. 그러나 그것은 조금 무의미 해 보인다.

본질적으로 Facade pattern을 구현하고 있지만 인터페이스를 더 단순하게 만들지는 않습니다. AsyncCallback 및 IAsyncResult를 사용하여 클래스에서 사용되는 속성을보다 정확하게 호출하도록 사용자 고유의 클래스를 추가하는 것이 더 좋을 수도 있습니다 (특정 상황에 따라 다름).

+0

Facade 패턴을 정의하는 글 머리 기호와 비교하여 OP가 수행하는 작업의 유사점을 볼 수 없습니다. – IAbstract

0

AsyncOperation 클래스와 SendOrPostCallback 대리자를 사용하여 호출자 스레드에서 이벤트가 발생하지 않도록 클래스가 다른 라이브러리에서 사용되도록하려는 경우 비동기 프로세스가 종료 될 때 알림 이벤트를 개인적으로 선호합니다. UI를 중단시킵니다. 그러나 비동기 작업이 동일한 어셈블리에서 실행되는 경우 비동기 호출을 수행하는 방법을 정의하기 위해 호출 코드를 선호합니다.

관련 문제