2011-10-04 63 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 */ } 
} 

现在

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

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

注意的是,上述实施连续方法(MandatoryMethod)将被异步执行:你可以按如下方式使用此代码。如果您希望同步执行(如您的示例中所示),则可以使用ContinueWith的过载,该过载需要TaskContinuationOptions并通过TaskContinuationOptions.ExecuteSynchronously

1

坦率地说,我非常确定你正在努力完成什么。直接使用Task构造函数或Task.Factory是你希望实现的优势吗?

至于在任务完成后需要执行的“强制方法”,请查看延续(例如Task.ContinueWith)。

+0

也许问题不够清楚。重点是为所有类型的'void'方法一般创建一个任务。 –