Выполнение задач в общем - PullRequest
1 голос
/ 04 октября 2011

В своем проекте я активно использую 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 методов для различного количества параметров.Но я не знаю, может ли создание слишком большого количества анонимных делегатов вызвать побочные эффекты.

Какой из них вы предпочитаете?Зачем?Или какие другие решения у вас есть?

Ответы [ 2 ]

3 голосов
/ 04 октября 2011

Что ж, вы всегда можете создать метод расширения на Action<TA,TB> ... и вам следует использовать продолжения, а не вызовы метода-обертки, чтобы реализовать поведение, всегда выполняющее другое действие после завершения задачи:1004 * Теперь вы можете использовать этот код следующим образом:

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

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

Обратите внимание, что в описанной выше реализации метод продолжения (MandatoryMethod) будет выполняться асинхронно.Если вы хотите синхронного выполнения (как это реализовано в вашем примере), вы можете использовать перегрузку ContinueWith, которая принимает TaskContinuationOptions и передает TaskContinuationOptions.ExecuteSynchronously.

1 голос
/ 04 октября 2011

Честно говоря, я не совсем уверен, что вы пытаетесь сделать с этим.Какое преимущество по сравнению с непосредственным использованием конструктора Task или Task.Factory вы надеетесь достичь?

Что касается "обязательного метода", который должен выполняться после завершения задачи, посмотрите на продолжения (например, Task.ContinueWith).

...