2011-10-04 6 views
1

내 프로젝트에서는 TPL을 많이 사용하며 명시 적으로 new Task(Action);, new Task(Action<object>, object); 또는 Task.Factory.StartNew(Action) 등을 명시 적으로 호출하는 대신 작업 생성 방법을 설계하기로했습니다. 나는 작업을 만들고 시작하기 위해일반적으로 작업 실행

void SpawnTask<A,B>(Action<A,B> action, A a, B b) { ... } 
void SpawnTask<A,B,C>(Action<A,B,C> action, A a, B b, C c) { ... } 

과 같은 기능을 갖습니다.

또한 각 작업을 완료 한 후에 필수 방법을 실행해야합니다. 따라서 나는 다른 메소드에서 실행하고 싶은 실제 메소드를 랩핑해야한다.

void RuncTask(Action action) 
{ 
    action(); 
    MandatoryMethod(); 
} 

지금까지 두 가지 접근법을 제시했다.
첫째, 사용 익명 대표 :

void SpawnTask<A,B>(Action<A,B> action, A a, B b) 
{ 
    A dummyA = a; // To localize the parameters. 
    B dummyB = b; 
    var methodDelegate = delegate { action(dummyA,dummyB); }; 
    var taskDelegate = delegate { RunTask(methodDelegate); }; 
    Task.Factory.StartNew(taskDelegate); 
} 

void RuncTask(Action action) 
{ 
    action(); 
    MandatoryMethod(); 
} 

둘째, 튜플 사용은 : 그것은 간단 때문에

void SpawnTask<A,B>(Action<A,B> action, A a, B b) 
{ 
    Tuple<Action<A,B>, A, B> tpl = Tuple.Create(action, a, b); 
    Action<object> act = RunTask<A,B>; 
    Task.Factory.StartNew(act, tpl); 
} 

void RuncTask<A,B>(object obj) 
{ 
    var tpl = (Tuple<Action<A, B>, A, B>)param; 
    tpl.Item1(tpl.Item2,tpl.Item3); 
    MandatoryMethod(); 
} 

내가 처음 일을 좋아한다. 두 번째는 캐스팅을 수행하기 때문에 다른 수의 매개 변수에 대해 다른 일반적인 RunTask 메소드를 구현해야합니다. 그러나 너무 많은 익명의 대리인을 만들면 부작용이 발생할 수 있는지 여부는 알 수 없습니다.

어느 쪽을 원하십니까? 왜? 아니면 다른 해결책이 있습니까?

답변

3

글쎄, 당신은 항상 Action<TA,TB>에 확장 메서드를 만들 수 있습니다 ... 당신은 포장 방법은 작업이 완료 될 때 항상 다른 작업을 수행하는 동작을 구현하기 위해 호출보다는 연속성을 사용해야합니다 : 이제

public static class TaskExtensions 
{ 
    public static void RunTask<TA,TB>(Action<TA,TB> action, TA a, TB b) 
    { 
     Task newTask = new Task(() => action(a,b)); 
     newTask.ContinueWith(MandatoryMethod); 
     newTask.Start(); 
    } 

    // if you need to support other signature (more parameters) you would need to 
    // create additional overloads of RunTask with more generic parameters... 
    public static void RunTask(Action action); 
    public static void RunTask<TA>(Action<TA> action, TA a); 
    // etc ... 

    private static void MandatoryMethod(Task t) { /* your continuation logic */ } 
} 

을 위의 구현에 계속 방법 (MandatoryMethod)를 비동기 적으로 실행됩니다

public void SomeMethod(int x, int y) { ... } 

// later... 
Action<int,int> myAction = SomeMethod; 
myAction.RunTask(1, 2); 

참고 : 다음과 같이이 코드를 사용할 수 있습니다. 동기 실행을 원할 경우 (예에서 구현 한 것처럼) ContinueWith의 오버로드에 TaskContinuationOptions을 사용하고 TaskContinuationOptions.ExecuteSynchronously을 전달할 수 있습니다.

1

솔직히, 나는 당신이 그걸로 성취하려고 노력하고 있다는 것을 확신합니다. Task 생성자 또는 Task.Factory을 직접 사용하면 어떤 이점을 얻을 수 있습니까?

작업 완료 후 실행해야하는 "필수 방법"은 계속 (예 : Task.ContinueWith)을 살펴보십시오.

+0

아마도 질문이 명확하지 않을 수 있습니다. 핵심은 모든 유형의'void' 메소드에 대한 태스크를 일반적으로 생성하는 것입니다. –